java.lang.Class

Class<T> — runtime-представление загруженного типа. Объекты, интерфейсы, массивы, примитивы и void имеют свои Class-объекты. Создать Class обычным конструктором нельзя: их создаёт JVM и загрузчики.

Class<String> stringType = String.class;
Class<?> runtimeType = value.getClass();
Class<?> arrayType = int[].class;
Class<?> primitiveType = int.class;

Идентичность класса — не только полное имя, но и определивший ClassLoader. Два загрузчика могут загрузить одинаковый bytecode как два несовместимых runtime-типа.

Что можно узнать

Class<Order> type = Order.class;
 
String name = type.getName();
boolean record = type.isRecord();
Constructor<Order> constructor =
        type.getDeclaredConstructor(String.class);
List<String> fieldNames = Arrays.stream(type.getDeclaredFields())
        .map(Field::getName)
        .toList();
  • getMethods() — публичные методы, включая унаследованные;
  • getDeclaredMethods() — методы, объявленные непосредственно здесь, любой видимости;
  • аналогичное различие есть для полей и конструкторов;
  • generic-метаданные доступны как Type, но runtime-объекты подчиняются type erasure.

Загрузка и инициализация

SomeType.class получает class literal без обязательного запуска static-инициализатора. Class.forName("pkg.SomeType") по умолчанию загружает и инициализирует тип. Перегрузка с initialize = false разделяет эти действия.

Class<?> metadataOnly = Class.forName(
        "example.Plugin",
        false,
        pluginLoader
);

Ограничения

  • reflection может быть ограничена модулями и доступом;
  • Class.forName со строкой переносит ошибку имени в runtime;
  • хранение Class<?> в статическом кэше может удерживать plugin ClassLoader;
  • Class.newInstance() устарел; нужен getDeclaredConstructor().newInstance().

На собеседовании

Могут ли два класса с одним именем быть разными? Да, если их определили разные загрузчики.

Чем getMethods отличается от getDeclaredMethods? Первый возвращает доступные публичные, включая наследованные; второй — объявленные в классе.

Инициализирует ли Type.class класс? Само class literal обычно нет.

Как получить Class примитива? Например, int.class или Integer.TYPE.

Связано: Понятие рефлективность Java, Class loader, Аннотации.