1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/wizardforcel-thinking-in-java-zh

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
В этом репозитории не указан файл с открытой лицензией (LICENSE). При использовании обратитесь к конкретному описанию проекта и его зависимостям в коде.
Клонировать/Скачать
11.2 RTTI语法.md 7.4 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
Отправлено 11.03.2025 09:15 d56454c

11.2 RTTI синтаксис

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

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

//: 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); }
}
``````java
public class ToyTest {
  public static void main(String[] args) {
    Class<?> c = null;
    try {
      c = Class.forName("FancyToy");
    } catch(ClassNotFoundException 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 {
      // Requires a default constructor:
      o = cy.newInstance(); // (*1*)
    } catch(InstantiationException e) {}
    catch(IllegalAccessException e) {}
    printInfo(o.getClass());
  }
}

Здесь текст внутри комментария был переведён:

// Требуется конструктор по умолчанию:

на

// Requires a default constructor:````markdown В этом примере класс FancyToyдовольно сложен, так как он наследует от классаToyи реализует интерфейсыHasBatteries, WaterproofиShootsThings. В методе main()создается ссылка на классClass, которая затем инициализируется значением FancyToyвнутри соответствующего блокаtry`.

Метод getInterfaces() класса Class возвращает массив объектов Class, представляющих интерфейсы, содержащиеся в данном объекте Class. Если имеется объект типа Class, можно использовать метод getSuperclass(), чтобы получить прямого родителя этого объекта. Этот метод вернет ссылку типа Class, которую можно использовать для дальнейших запросов. Это означает, что во время выполнения программы есть возможность полностью исследовать иерархию наследования объекта. ```На первый взгляд может показаться, что метод newInstance() класса `Class` является альтернативой методу клонирования (`clone()`). Однако эти два подхода имеют различия. Используя `newInstance()`, мы можем создать новый объект даже в том случае, если нет существующего объекта для "клонирования". Как демонстрируется в примере выше, когда нет объекта типа `Toy`, имеется ссылка на объект типа `Class`, который представляет класс `Toy`. Эта ссылка позволяет нам создать "виртуальный конструктор", то есть сказать: "Независимо от того, какой именно тип ты представляешь, пожалуйста, создай себя правильно." В данном контексте ссылка `cy` является просто ссылкой на объект типа `Class`, и компилятор не имеет информации о конкретном типе до создания нового экземпляра. После создания нового экземпляра получаем ссылку типа `Object`, но она указывает на объект типа `Toy`. Для отправки сообщений, кроме тех, которые могут принимать объекты типа `Object`, потребуется дополнительное преобразование. Кроме того, класс, созданный с помощью `newInstance()`, должен иметь конструктор по умолчанию. Создание объектов с использованием других конструкторов через `newInstance()` невозможно, поэтому в Java 1.0 могли возникнуть ограничения. Тем не менее, API "рефлексии" в Java 1.1 (обсуждается в следующем разделе) позволяет нам динамически использовать любой конструктор внутри класса.Последний метод в программе — это `printInfo()`, который принимает ссылку на объект типа `Class`, использует метод `getName()` для получения имени класса и метод `isInterface()` для проверки, является ли данный класс интерфейсом.

Выходные данные программы следующие:

Имя класса: FancyToy - является интерфейсом? [false]
Имя класса: HasBatteries - является интерфейсом? [true]
Имя класса: Waterproof - является интерфейсом? [true]
Имя класса: ShootsThings - является интерфейсом? [true]
Имя класса: Toy - является интерфейсом? [false]

С помощью объекта типа Class можно практически полностью исследовать иерархию наследования объекта.

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/wizardforcel-thinking-in-java-zh.git
git@api.gitlife.ru:oschina-mirror/wizardforcel-thinking-in-java-zh.git
oschina-mirror
wizardforcel-thinking-in-java-zh
wizardforcel-thinking-in-java-zh
master