Чтение онлайн

ЖАНРЫ

Философия Java3

Эккель Брюс

Шрифт:

}

}

} ///:-

Каждый класс реализует некоторое понятие «счетности». В случае Counting-Generator.Character это повторение символов верхнего и нижнего регистра. Класс CountingGenerator.String использует CountingGenerator.Character для заполнения массива символов, который затем преобразуется в String. Размер массива определяется аргументом конструктора. Обратите внимание на то, что CountingGenerator.String использует базовую конструкцию Generator<java.lang. Character вместо конкретной ссылки на CountingGenerator.Character.

Следующая

тестовая программа использует рефлексию с идиомой вложенных генераторов, что позволяет применять ее для любого набора генераторов, построенного по указанному образцу:

//: arrays/GeneratorsTest.java import net.mindview.util.*;

public class GeneratorsTest {

public static int size = 10;

public static void test(Class<?> surroundingClass) {

for(Class<?> type : surroundingClass.getClassesO) {

System.out.print(type.getSimpleName + ": "); try {

Generator<?> g = (Generator<?>)type.newInstance; for(int i = 0; i < size; i++)

System.out printf(g.next + " "); System, out. printlnO; } catch(Exception e) {

throw new RuntimeException(e);

}

}

}

public static void main(String[] args) { test(CountingGenerator.class);

}

} /* Output;

Double; 0.0 1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0 Float; 0.0 1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0 Long; 0 12 3 4 5 6 7 8 9 Integer; 0 1 2 3 4 5 6 7 8 9 Short; 0 12 3 4 5 6 7 8 9

String: abcdefg hijklmn opqrstu vwxyzAB CDEFGHI JKLMNOP QRSTUVW XYZabcd efghijk lmnopqr Character: abcdefghi j Byte: 0 12 3 4 5 6 7 8 9

Boolean: true false true false true false true false true false *///:-

Предполагается, что тестируемый класс содержит серию вложенных объектов Generator, каждый из которых имеет конструктор по умолчанию (то есть без аргументов). Рефлексионный метод getClasses выдает информацию обо всех вложенных классах. Далее метод test создает экземпляр каждого генератора и выводит результаты, полученные при десятикратном вызове next.

Следующий набор генераторов основан на случайных числах. Так как конструктор Random инициализируется константой, результаты будут повторяться при каждом запуске программы:

//: net/mi ndvi ew/uti1/RandomGenerator.java // Генераторы, выдающие случайные значения, package net.mi ndvi ew.uti1; import java.util.*;

public class RandomGenerator {

private static Random r = hew Random(47);

public static class

Boolean implements Generator<java lang Boolean> { public java lang Boolean nextO { return r nextBooleanO;

}

}

public static class

Byte implements Generator<java lang Byte> { public java lang Byte nextO {

return (byte)r nextlntO;

}

}

public static class

Character implements Generator<java.lang Character { public java lang Character nextO {

return CountingGenerator.charsE

r nextInt(CountingGenerator.chars.length)],

}

}

public static class

String extends CountingGenerator.String {

//

Подключение случайного генератора Character { eg = new CharacterO; } // Инициализатор public StringO {}

public String(int length) { super(1ength), }

}

public static class

Short implements Generator<java.lang Short> { public java.lang Short nextO {

return (short)r.nextlntO.

}

}

public static class

Integer implements Generator<java lang.Integer> { private int mod = 10000; public IntegerО {}

public Integer(int modulo) { mod = modulo; } public java lang Integer nextO { return r.nextlnt(mod);

}

}

public static class

Long implements Generator<java.lang.Long> { private int mod = 10000. public LongO {}

public Long(int modulo) { mod = modulo; } public java lang.Long nextO {

return new java.lang.Long(r nextInt(mod));

}

}

public static class

Float implements Generator<java lang Float> { public java.lang.Float nextO {

// Отсечение до двух разрядов в дробной части, int trimmed = Math.round(r nextFloatO * 100). return ((float)trimmed) / 100.

}

} ///:-

Как видите, RandomGenerator.String наследует от CountingGenerator.String, просто подключая новый генератор Character.

Чтобы генерируемые числа были не слишком велики, RandomGenerator. Integer по умолчанию берет остаток от деления на 10 ООО, но перегруженный конструктор позволяет выбрать меньшее значение. Аналогичный подход используется и для RandomGenerator.Long. Для генераторов Float и Double цифры в дробной части усекаются.

Для тестирования RandomGenerator можно воспользоваться уже готовым классом GeneratorsTest:

//: arrays/RandomGeneratorsTest.java import net.mindview util.*;

public class RandomGeneratorsTest {

public static void main(String[] args) {

GeneratorsTest test(RandomGenerator.class);

}

} /* Output:

Double: 0.73 0.53 0.16 0 19 0.52 0.27 0.26 0.05 0.8 0.76 Float: 0.53 0,16 0.53 0.4 0.49 0.25 0.8 0.11 0.02 0.8 Long: 7674 8804 8950 7826 4322 896 8033 2984 2344 5810 Integer: 8303 3141 7138 6012 9966 8689 7185 6992 5746 3976 Short: 3358 20592 284 26791 12834 -8092 13656 29324 -1423 5327

String: bklnaMe sbtWHkj UrUkZPg wsqPzDy CyRFJQA HxxHvHq XumcXZJ oogoYWM NvqeuTp nXsgqia Character: xxEAJJmzMs Byte: -60 -17 55 -14 -5 115 39 -37 79 115 Boolean: false true false false true true true true true true *///:-

Чтобы изменить количество генерируемых значений, воспользуйтесь public-полем GeneratorsTest.size.

Создание массивов с использованием генераторов

Для создания массивов на основе Generator нам потребуются два вспомогательных класса. Первый использует произвольный Generator для получения массива типов, производных от Object. Для решения проблемы с примитивами второй класс получает произвольный массив с объектами-«обертками» и строит для него соответствующий массив примитивов.

Поделиться с друзьями: