Автор оригинала: 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 .