Клас Class

Для кожного класу і інтерфейсу в системі є що представляє його обєкт Class Цей обєкт може використовуватися для отримання основних відомостей про клас або інтерфейсі і для створення нових обєктів класу

дозволяє переміщатися по ієрархії типів в програмі Така ієрархія фактично стає частиною програмного середовища, що полегшує процес налагодження та автоматичного документування, а також робить програму більш послідовною Крім того, це відкриває нові можливості роботи з класами – в першу чергу для створення обєктів (їх тип може здаватися у вигляді рядка) і виклику класів з використанням спеціальних прийомів (наприклад, завантаження по мережі)

Існує два способи отримати обєкт Class: запитати його у наявного обєкта методом getClass або шукати його за уточненим (включающему всі імена пакетів) імені статичним методом ClassforName

Найпростіші методи Class призначені для переміщення по ієрархії типів

Наведений нижче клас виводить таку ієрархію для конкретного обєкта Class:

public class TypeDesc {

public static void main(String[] args) { TypeDesc desc = new TypeDesc()

for (int i = 0 i &lt&lt argslength i++) {

try {

descprintType(ClassforName(args[i]),  0)

} Catch (ClassNotFoundException e) {Systemerrprint (e) / / Повідомити про помилку

}

}

/ / За замовчуванням працювати зі стандартним висновком

public javaioPrintStream out = Systemout

/ / Використовується в printType () для позначки імен типів

private static String[]

basic    = { &quotclass&quot,   &quotinterface&quot   }, extended = { &quotextends&quot, &quotimplements&quot  }

public void printType(Class type, int depth) {

if (type == null) / / супертіп Object дорівнює null return

/ / Вивести тип

for (int i = o i &lt&lt depth i++)

outprint(&quot  &quot)

String[] labels = (depth == 0 basic : extended) outprint(labels[typeisInterface()   1 : 0] +  &quot &quot) outprintln(typegetName())

/ / Вивести інтерфейси, реалізовані класом Class [] interfaces = typegetInterfaces () for (int i = o i << interfaces.length; i + +)

printType(interfaces[i], depth + 1)

/ / Рекурсивний виклик для суперкласу

printType(typegetSuperclass(), depth + 1)

}

}

Даний приклад переглядає імена, введені в командному рядку, і викликає printType для кожного з них Робити це необхідно в try-блоці на той випадок, якщо клас із заданим імям відсутня Нижче показаний результат роботи програми для класу javautilHashtable (використовується повне уточнене імя, оскільки цього вимагає метод forName):

class javautilHashtable

implements javalangCloneable extends javalangObject

extends javautilDictionary

extends javalangObject

Далі в тексті програми слід оголошення вихідного потоку Для стислості ми оголосили його відкритим, але в реальному додатку він повинен бути закритим, а звернення до нього повинні здійснюватися тільки через методи доступу Потім слід опис двох строкових масивів

Метод printType виводить опис свого типу, а потім рекурсивно викликає себе для роздруківки властивостей супертіпа Параметр depth показує, на скільки рівнів ми піднялися в ієрархії типів залежно від його значення кожен рядок з описом забезпечується відповідним відступом З кожним новим рівнем рекурсії це значення збільшується

При виведенні типу метод isInterface визначає, чи є тип інтерфейсом Результат виклику використовується для вибору префікса – пояснювальній написи У самому низу ієрархії типів, де значення depth одно 0, виводяться написи class і interface; типи, що знаходяться вище в ієрархії, розширюють або реалізують свої вихідні типи, тому використовуються терміни extends і implements. Саме для цього і створюються масиви Basic і Extended Після вибору потрібного префікса імя типу виводиться методом getName Звичайно, клас Class містить метод toString, однак у цьому методі вже використаний префікс class або interface. Ми хочемо самі контролювати префікс, і тому довелося створити власну реалізацію методу

Після виведення опису типу метод printType здійснює рекурсивний виклик себе самого Спочатку визначаються всі інтерфейси, реалізовані вихідним типом / Якщо тип, для якого виводиться інформація, являє собою інтерфейс, то він розширює, а не реалізує свої інтерфейси-супертіпи Проте, облік таких подробиць привів би до невиправданого ускладнення коду / Потім виводиться розширюваний їм суперклас (Якщо він існує) Поступово метод доходить до обєкта Class класу Object, який не реалізує ніяких інтерфейсів і для якого метод getSuperClass повертає null

на цьому рекурсія завершується

Вправа 131

Модифікуйте TypeDesc, щоб уникнути виведення інформації про клас Object Ці відомості надлишкові, оскільки кожен обєкт в кінцевому рахунку розширює клас Object Використовуйте посилання на обєкт Class для типу Object

Обєкт Class може скористатися методом newInstance для створення нового екземпляра (обєкта) представленого ним типу При цьому викликається безаргументний конструктор класу або збуджується виключення NoSuch MethodError, якщо клас не має безаргументний конструктора Якщо клас або безаргументний конструктор недоступні (не є відкритими або знаходяться в іншому пакеті), збуджується виключення IllegalAccessException Якщо клас є абстрактним, або являє собою інтерфейс, або створення завершилося невдало з якоїсь іншої причини, збуджується виключення InstantiationException Створювати нові обєкти подібним чином виявляється зручно, коли ви хочете написати універсальний код і дозволити

користувачеві задати потрібний клас Наприклад, в програмі тестування алгоритмів сортування, наведеною в розділі Проектування расширяемого класу, користувач міг ввести імя тестованого класу і використовувати його як параметр для виклику forName Якщо введене імя класу виявиться допустимим, можна викликати метод newInstance для створення обєкта цього типу Метод main для універсального класу SortDouble виглядає наступним чином:

static double[] testData = { 03, 13e-2 79 317, )

public static void main(String[] args) {

try {

for (int arg = 0 arg &lt&lt argslength arg++) { String name = args[arg]

Class classFor = ClassforName(name) SortDouble sorter

= (SortDouble)classFornewInstance()

SortMetrics metrics

= sortersort(testData) Systemoutprintln(name + &quot: &quot + metrics) for (int i = 0 i &lt&lt testDatalength i++)

Systemoutprintln(&quot\t&quot + testData[i])

}

} catch (Exception e) {

Systemerrprint (e) / / Повідомити про помилку

}

}

Цей метод майже збігається з BubbleSortDoublemain, проте з нього виключені всі імена типів Він застосовується до будь-якого типу, обєкти якого можуть використовуватися в якості обєктів SortDouble і який містить безаргументний конструктор Тепер нам не доведеться переписувати метод main для кожного алгоритму сортування – універсальний main годиться для всіх випадків Все, що потрібно зробити, – виконати команду

java SortDouble TestClass ..

для будь-якого класу-сортувальника (на зразок BubbleSortDouble) клас буде завантажений і виконаний

Джерело: Арнольд К, Гослінг Д – Мова програмування Java (1997)

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*