Перейти к основному содержимому

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

· 5 мин. чтения

1. Обзор

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

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

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

Начнем с метода getSimpleName() .

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

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

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

package com.foreach.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.foreach.className.RetrieveClassName", RetrieveClassName.class.getName());
assertEquals("com.foreach.className.RetrieveClassName", RetrieveClassName.class.getTypeName());
assertEquals("com.foreach.className.RetrieveClassName", RetrieveClassName.class.getCanonicalName());

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

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

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

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

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

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

public class RetrieveClassName {
public class InnerClass {}
}

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

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

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

Еще одним исключением являются анонимные классы.

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

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

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

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

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

3.5. Массивы

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

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

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

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

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

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

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

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

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

4. Вывод

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

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

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