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

Получение имени класса в Java

Изучите различные способы получения имени класса в Java.

Автор оригинала: François Dupire.

1. Обзор

В этом уроке мы узнаем о четырех способах извлечения имени класса из методов Class API: getSimpleName () , getName () , getTypeName() и getCanonicalName() .

Эти методы могут сбивать с толку из-за их схожих названий и их несколько расплывчатых Javadoc. Они также имеют некоторые нюансы, когда речь заходит о примитивных типах, типах объектов, внутренних или анонимных классах и массивах.

2. Получение Простого Имени

Давайте начнем с метода getSimpleName () .

В Java существует два типа имен: простые и квалифицированные . Простое имя состоит из уникального идентификатора, в то время как полное имя представляет собой последовательность простых имен, разделенных точками.

Как следует из его названия, getSimpleName() возвращает простое имя базового класса, то есть имя, которое было дано в исходном коде .

Давайте представим себе следующий класс:

package com.baeldung.className;
public class RetrieveClassName {}

Его простое имя будет RetrieveClassName :

assertEquals("RetrieveClassName", RetrieveClassName.class.getSimpleName());

Мы также можем получить примитивные типы и массивы простых имен. Для примитивных типов, которые будут просто их именами, например int, boolean или float .

А для массивов метод вернет простое имя типа массива, за которым следует пара открывающих и закрывающих скобок для каждого измерения массива ([]) :

RetrieveClassName[] names = new RetrieveClassName[];
assertEquals("RetrieveClassName[]", names.getClass().getSimpleName());

Следовательно, для двумерного String массива вызов getSimpleName() в его классе вернет String[][] .

Наконец, есть конкретный случай анонимных классов. Вызов getSimpleName() в анонимном классе вернет пустую строку.

3. Получение Других Имен

Теперь пришло время взглянуть на то, как мы могли бы получить имя класса, имя типа или каноническое имя. В отличие от getSimpleName() , эти имена предназначены для предоставления дополнительной информации о классе.

Метод getCanonicalName() всегда возвращает каноническое имя , определенное в спецификации языка Java .

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

3.1. Примитивные типы

Давайте начнем с примитивных типов, поскольку они просты. Для примитивных типов все три метода getName (), getTypeName() и getCanonicalName() вернут тот же результат, что и getSimpleName() :

assertEquals("int", int.class.getName());
assertEquals("int", int.class.getTypeName());
assertEquals("int", int.class.getCanonicalName());

3.2. Типы объектов

Теперь мы посмотрим, как эти методы работают с типами объектов. Их поведение, как правило, одинаковое: все они возвращают каноническое имя класса .

В большинстве случаев это полное имя, которое содержит все простые имена пакетов классов, а также простое имя класса:

assertEquals("com.baeldung.className.RetrieveClassName", RetrieveClassName.class.getName());
assertEquals("com.baeldung.className.RetrieveClassName", RetrieveClassName.class.getTypeName());
assertEquals("com.baeldung.className.RetrieveClassName", RetrieveClassName.class.getSimpleName());

3.3. Внутренние классы

То, что мы видели в предыдущем разделе, – это общее поведение этих вызовов методов, но есть несколько исключений.

Внутренние классы-один из них. Методы getName() и getTypeName() ведут себя иначе, чем метод getCanonicalName() для внутренних классов.

getCanonicalName() по-прежнему возвращает каноническое имя класса , то есть каноническое имя заключающего класса плюс простое имя внутреннего класса, разделенное точкой.

С другой стороны, методы getName() и getTypeName() возвращают почти то же самое, но используют доллар в качестве разделителя между каноническим именем заключающего класса и простым именем внутреннего класса .

Давайте представим себе внутренний класс InnerClass нашего RetrieveClassName :

public class RetrieveClassName {
    public class InnerClass {}
}

Затем каждый вызов обозначает внутренний класс немного по-другому:

assertEquals("com.baeldung.RetrieveClassName.InnerClass", 
  RetrieveClassName.InnerClass.class.getCanonicalName());
assertEquals("com.baeldung.RetrieveClassName$InnerClass", 
  RetrieveClassName.InnerClass.class.getName());
assertEquals("com.baeldung.RetrieveClassName$InnerClass", 
  RetrieveClassName.InnerClass.class.getTypeName());

3.4. Анонимные классы

Анонимные классы-еще одно исключение.

Как мы уже видели, у них нет простого имени, но у них также нет канонического имени . Поэтому getCanonicalName() ничего не возвращает. В отличие от getSimpleName() , getCanonicalName() вернет null | и не пустую строку при вызове анонимного класса.

Что касается getName() и getTypeName () , они вернут каноническое имя вызывающего класса, за которым последуют доллар и число, представляющее положение анонимного класса среди всех анонимных классов, созданных в вызывающем классе .

Давайте проиллюстрируем это на примере. Мы создадим здесь два анонимных класса и вызовем getName() на первом и getTypeName() на втором, объявив их в com.baeldung.Главная :

assertEquals("com.baeldung.Main$1", new RetrieveClassName() {}.getClass().getName());
assertEquals("com.baeldung.Main$2", new RetrieveClassName() {}.getClass().getTypeName());

Следует отметить, что второй вызов возвращает имя с увеличенным числом в конце, поскольку оно применяется ко второму анонимному классу.

3.5. Массивы

Наконец, давайте посмотрим, как массивы обрабатываются вышеперечисленными тремя методами.

Чтобы указать, что мы имеем дело с массивами, каждый метод обновит свой стандартный результат. Методы getTypeName() и getCanonicalName() добавят пары скобок к своему результату.

Давайте рассмотрим следующий пример, в котором мы вызываем getTypeName() и getCanonicalName() для двумерного внутреннего класса массива:

assertEquals("com.baeldung.RetrieveClassName$InnerClass[][]", 
  RetrieveClassName.InnerClass[][].class.getTypeName());
assertEquals("com.baeldung.RetrieveClassName.InnerClass[][]", 
  RetrieveClassName.InnerClass[][].class.getCanonicalName());

Обратите внимание, как первый вызов использует доллар вместо точки, чтобы отделить внутреннюю часть класса от остальной части имени.

Теперь давайте посмотрим, как работает метод getName () . При вызове массива примитивного типа он возвращает открывающую скобку и букву, представляющую примитивный тип . Давайте проверим это на следующем примере, вызвав этот метод для двумерного массива примитивных целых чисел:

assertEquals("[[I", int[][].class.getName());

С другой стороны, при вызове массива объектов он добавит открывающую скобку и букву L к своему стандартному результату и завершится точкой с запятой . Давайте попробуем это на массиве RetrieveClassName :

assertEquals("[Lcom.baeldung.className.RetrieveClassName;", RetrieveClassName[].class.getName());

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

В этой статье мы рассмотрели четыре метода доступа к имени класса в Java. Эти методы: getSimpleName(), getName(), getTypeName() и getCanonicalName() .

Мы узнали, что первый просто возвращает имя исходного кода класса, в то время как другие предоставляют дополнительную информацию, такую как имя пакета и указание на то, является ли класс внутренним или анонимным классом.

Код этой статьи можно найти на GitHub .