Философия Java

Синтаксис RTTI


Java выполняет RTTI, используя объект Class, даже если Вы делаете что-то похожее на приведение. Класс Class также предоставляет Вам несколько путей использования RTTI.

Вначале, Вы должны получить ссылку на соответствующий объект Class. Один способ сделать это, как показано в предыдущем примере, использовать строку и метод Class.forName( ). Это удобно потому, что Вам не нужен объект того типа для получения ссылки на Class. Однако, если у Вас уже есть объект того типа, который Вам нужен, то Вы можете получить ссылку на Class вызовом метода, который является частью базового класса Object: getClass( ). Он возвращает ссылку на Class представляя действительный тип объекта. Объект Class содержит много интересных методов, показанных в следующем примере:

//: c12:ToyTest.java // Тестирование класса Class.

interface HasBatteries {} interface Waterproof {} interface ShootsThings {} class Toy { // Закоментируйте следующий конструктор // по умолчанию и увидите // NoSuchMethodError на(*1*) Toy() {} Toy(int i) {} }

class FancyToy extends Toy implements HasBatteries, Waterproof, ShootsThings { FancyToy() { super(1); } }

public class ToyTest { public static void main(String[] args) throws Exception { Class c = null; try { c = Class.forName("FancyToy"); } catch(ClassNotFoundException e) { System.err.println("Can't find FancyToy"); throw e; } printInfo(c); Class[] faces = c.getInterfaces(); for(int i = 0; i < faces.length; i++) printInfo(faces[i]); Class cy = c.getSuperclass(); Object o = null; try { // Требуется конструктор по умолчанию: o = cy.newInstance(); // (*1*) } catch(InstantiationException e) { System.err.println("Cannot instantiate"); throw e; } catch(IllegalAccessException e) { System.err.println("Cannot access"); throw e; } printInfo(o.getClass()); } static void printInfo(Class cc) { System.out.println( "Class name: " + cc.getName() + " is interface? [" + cc.isInterface() + "]"); } } ///:~


Вы видите, что классFancyToy является очень запутанным, т.к. он наследуется от Toy и реализует интерфейсы HasBatteries, Waterproof и ShootsThings. В методе main( ), создается ссылка на Class и инициализируется классом FancyToy Class с помощью forName( ) внутри соответствующего блока try.
Метод объекта Class.getInterfaces( ) возвращает массив объектов Class представляющих интерфейсы, содержащиеся в интересующем нас объекте Class.
Если у Вас есть объект Class, Вы можете узнать у него о непосредственном базовом классе, используя метод getSuperclass( ). Он, конечно, возвращает ссылку на Class, которую в дальнейшем Вы можете использовать для получения информации. Это значит, что во время выполнения, Вы можете определить всю иерархию классов.
Метод newInstance( ) объекта Class может, вначале, показаться еще одним способом дублирования объекта, как это делает метод clone( ). Однако, с помощью newInstance( ), Вы можете создавать объекты без существующего объекта, как показано здесь, объект Toy не существует—только указатель cy, который является ссылкой на объект Class. Это - способ реализовать “виртуальный конструктор”, который позволяет Вам сказать “Я не знаю точно какого типа объект, но я корректно его создаю”. В примере, приведенном выше, cy - просто ссылка на Class, без всякой дополнительной информации во время компиляции. И когда Вы создаете новый экземпляр, Вам возвращается ссылка на Object. Но эта ссылка указывает на объект Toy. Конечно, перед тем как Вы сможете получить п доступ к элементам класса, отличным от реализованных в классе Object, Вам нужно его немного исследовать, и сделать пребразование типа. В дополнение ко всему, класс, созданный с помощью newInstance( ) должен иметь конструктор по умолчанию. В следующем разделе, Вы увидите, как динамически создавать объекты классов, используя API рефлексии в Java.
Последний метод в тексте программы это printInfo( ), который берет ссылку класса Class получает его имя с помощью getName( ), а затем определяет, является ли он интерфейсом с помощью функции isInterface( ).
Результаты работы программы:
Class name: FancyToy is interface? [false] Class name: HasBatteries is interface? [true] Class name: Waterproof is interface? [true] Class name: ShootsThings is interface? [true] Class name: Toy is interface? [false]
Итак, с помощью объекта Class Вы можете узнать все что угодно об объекте.

Содержание раздела