Рубрики
Без рубрики

Разница между.getClass() и A.class на Java

Узнайте о различиях между вызовом метода Object.getClass() и использованием синтаксиса .class

Автор оригинала: Kai Yuan.

1. Обзор

В Java/| класс java.lang.Класс является точкой входа всех операций отражения . Как только у нас будет объект java.lang.Класс , затем мы можем вызвать соответствующие методы, чтобы получить объекты классов отражения.

В этом уроке мы обсудим различия между двумя различными способами получения объекта java.lang.Класс :

  • Вызов метода Object.getClass()
  • Использование синтаксиса .class

2. Краткое введение в два подхода

Метод Object.getClass() является методом экземпляра класса Object . Если у нас есть объект, мы можем вызвать object.getClass () , чтобы получить Класс объект его типа.

Аналогично, мы можем использовать ClassName.class синтаксис для получения класса объекта типа. Пример может объяснить это ясно:

@Test
public void givenObjectAndType_whenGettingClassObject_thenTwoMethodsHaveTheSameResult() {
    String str = "I am an object of the String class";

    Class fromStrObject = str.getClass();
    Class clazz = String.class;

    assertSame(fromStrObject, clazz);
}

В приведенном выше методе тестирования мы пытаемся получить объект Class класса String , используя два упомянутых нами способа. Наконец, метод утверждения говорит нам, что два объекта Class являются одним и тем же экземпляром.

Однако между этими двумя подходами существуют различия. Давайте рассмотрим их поближе.

3. Тип среды выполнения по сравнению с статический тип

Давайте быстро рассмотрим предыдущий пример. Когда мы вызываем метод str.getClass () , мы получаем тип времени выполнения объекта str . С другой стороны, String.class вычисляет String класс статически . В этом примере тип среды выполнения story и String.class одинаковы.

Однако они могут отличаться, если к партии присоединяется наследование классов. Давайте рассмотрим два простых класса:

public class Animal {
    protected int numberOfEyes;
}

public class Monkey extends Animal {
    // monkey stuff
}

Теперь давайте создадим экземпляр объекта класса Animal и проведем еще один тест:

@Test
public void givenClassInheritance_whenGettingRuntimeTypeAndStaticType_thenGetDifferentResult() {
    Animal animal = new Monkey();

    Class runtimeType = animal.getClass();
    Class staticType = Animal.class;

    assertSame(staticType, runtimeType);
}

Если мы запустим тест выше, мы получим сбой теста:

java.lang.AssertionError: ....
Expected :class com.baeldung.getclassobject.Animal
Actual   :class com.baeldung.getclassobject.Monkey

В тестовом методе, даже если мы создали экземпляр объекта animal с помощью Animal Monkey(); вместо Monkey Monkey(); , тип времени выполнения объекта animal по-прежнему Monkey. Это связано с тем, что объект animal является экземпляром Monkey во время выполнения.

Однако, когда мы получаем статический тип класса Animal , тип всегда Animal .

4. Обработка примитивных Типов

Когда мы пишем Java-код, мы довольно часто используем примитивные типы. Давайте попробуем получить Класс объект примитивного типа, используя подход object.getClass() :

int number = 7;
Class numberClass = number.getClass();

Если мы попытаемся скомпилировать приведенный выше код, мы получим ошибку компиляции:

Error: java: int cannot be dereferenced

Компилятор не может разыменовать переменную number , поскольку она является примитивной переменной. Поэтому метод object.getClass() не может помочь нам получить Class объект примитивного типа.

Давайте посмотрим, сможем ли мы получить примитивный тип, используя синтаксис .class :

@Test
public void givenPrimitiveType_whenGettingClassObject_thenOnlyStaticTypeWorks() {
    Class intType = int.class;
    assertNotNull(intType);
    assertEquals("int", intType.getName());
    assertTrue(intType.isPrimitive());
}

Таким образом, мы можем получить Класс объект типа int примитива через int.class . В Java версии 9 и более поздних версиях объект Class примитивного типа принадлежит модулю java.base .

Как показывает тест, синтаксис . class – это простой способ получить объект Class примитивного типа.

5. Получение класса Без экземпляра

Мы узнали, что метод object.getClass() может дать нам объект Class своего типа времени выполнения.

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

public abstract class SomeAbstractClass {
    // ...
}

interface SomeInterface {
   // some methods ...
}

public class SomeUtils {
    private SomeUtils() {
        throw new RuntimeException("This Util class is not allowed to be instantiated!");
    }
    // some public static methods...
}

В этих случаях мы не можем получить Class объекты этих типов с помощью метода object.getClass () , но мы все еще можем использовать синтаксис .class для получения Class объектов из них:

@Test
public void givenTypeCannotInstantiate_whenGetTypeStatically_thenGetTypesSuccefully() {
    Class interfaceType = SomeInterface.class;
    Class abstractClassType = SomeAbstractClass.class;
    Class utilClassType = SomeUtils.class;

    assertNotNull(interfaceType);
    assertTrue(interfaceType.isInterface());
    assertEquals("SomeInterface", interfaceType.getSimpleName());

    assertNotNull(abstractClassType);
    assertEquals("SomeAbstractClass", abstractClassType.getSimpleName());

    assertNotNull(utilClassType);
    assertEquals("SomeUtils", utilClassType.getSimpleName());
}

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

Поэтому, когда мы хотим иметь объект Class , но не можем получить экземпляр типа, синтаксис .class – это правильный путь.

6. Заключение

В этой статье мы изучили два различных способа получения объекта типа Class : метод object.getClass() и синтаксис .class .

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

объект.getClass() Тип объекта во время выполнения
Объекты класса Тип объекта во время выполнения Статический тип SomeClass
Примитивные типы Работает прямолинейно
Интерфейсы, абстрактные классы или классы, которые не могут быть созданы Работает прямолинейно

Как всегда, полный исходный код статьи доступен на GitHub .