Отримання імені класу на Java

1. Огляд

У цьому посібнику ми дізнаємося про чотири способи отримання імені класу з методів на API класу : getSimpleName (), getName (), getTypeName () і getCanonicalName ().

Ці методи можуть заплутати через схожі назви та дещо розмиті Javadocs. Вони також мають деякі нюанси, коли мова йде про примітивні типи, типи об’єктів, внутрішні або анонімні класи та масиви.

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.Main :

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

Слід зазначити, що другий виклик повертає ім’я із збільшеним числом у кінці, оскільки воно застосовується до другого анонімного класу.

3.5. Масиви

Нарешті, давайте подивимося, як обробляються масиви за допомогою вищезазначених трьох методів.

Щоб вказати, що ми маємо справу з масивами, кожен метод оновить свій стандартний результат. Методи getTypeName () та getCanonicalName () додадуть пари дужок до їх результату.

Давайте подивимось на наступний приклад, де ми викликаємо getTypeName () та getCanonicalName () на двовимірному масиві InnerClass :

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.