Вступление
Эта статья является продолжением серии статей, описывающих часто забываемые методы базового класса Object языка Java. Ниже приведены методы базового объекта Java, присутствующие во всех объектах Java из-за неявного наследования объекта, а также ссылки на каждую статью этой серии.
- нанизывать
- getClass (вы здесь)
- равно
- хэш-код
- клон
- завершить
- ждать и уведомлять
В центре внимания этой статьи - метод getClass()
, который
используется для доступа к метаданным о классе объекта, с которым вы
работаете.
Метод getClass ()
Несколько сбивающий с толку или неправильно понятый метод объекта
getClass()
возвращает экземпляр класса Class, который содержит
информацию о классе, из которого был вызван getClass()
Уф, если вы еще
не запутались этим последним утверждением, хорошо для вас, потому что я
и написал его!
Позвольте мне попытаться раскрыть это предложение, продемонстрировав,
как его можно использовать. Ниже вы найдете Person
я использовал в
первой статье о методе toString()
package com.adammcquistan.object;
import java.time.LocalDate;
public class Person {
private String firstName;
private String lastName;
private LocalDate dob;
public Person(String firstName, String lastName, LocalDate dob) {
this.firstName = firstName;
this.lastName = lastName;
this.dob = dob;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public LocalDate getDob() {
return dob;
}
public void setDob(LocalDate dob) {
this.dob = dob;
}
@Override
public String toString() {
return "<Person: firstName=" + firstName + ", lastName=" + lastName + ", dob=" + dob + ">";
}
}
Давайте сосредоточимся на переопределенном toString()
, который
перечисляет имя класса Person вместе со значениями полей экземпляра.
Вместо «жесткого кодирования» имени класса Person в самой строке я мог
бы фактически использовать метод getClass()
для возврата экземпляра
класса Class, который будет содержать эту информацию и позволит мне
использовать ее как так:
public class Person {
// omitting everyting else remaining the same
@Override
public String toString() {
Class c = getClass();
return "<" + c.getName() + ": firstName=" + firstName + ", lastName=" + lastName + ", dob=" + dob + ">";
}
}
Это приведет к замене исходного жестко запрограммированного текста
«Person» на полное имя класса «com.adammcquistan.object.Person». Класс
Class наполнен различными методами, которые позволяют идентифицировать
все аспекты объекта класса, для которого был вызван getClass()
Например, если я хотел бы получить более упрощена toString()
представление моего Person
класса я мог бы просто поменять на
c.getName()
вызов с c.getSimpleName()
, как показано ниже. Это, в
свою очередь, вернет «Человек» вместо полного имени класса
«com.adammcquistan.object.Person».
public class Person {
// omitting everyting else remaining the same
@Override
public String toString() {
Class c = getClass();
return "<" + c.getSimpleName() + ": firstName=" + firstName + ", lastName=" + lastName + ", dob=" + dob + ">";
}
}
Основное различие в семантике использования getClass()
по сравнению с
другими Object
заключается в том, что getClass()
нельзя
переопределить, поскольку он объявлен как final
метод.
Для чего подходит объект класса?
В этот момент вы можете спросить себя: «Хорошо, я думаю, это довольно
круто, что я могу получить информацию о классе, вызвав getClass () и
получив его представление объекта Class, но как это полезно для меня как
программиста?». Поверьте, я тоже задавал себе этот вопрос, и мой общий
вывод был ... это не так. По крайней мере, это не совсем так с точки
зрения обычного программиста . Однако, если вы являетесь разработчиком
библиотеки или фреймворка, вы, вероятно, хорошо познакомитесь с
информацией и поведением Class
потому что это важно для концепции,
известной как
отражение
.
Отражение позволяет выполнять две основные задачи: (i) исследование объектов и их содержимого во время выполнения и (ii) динамический доступ к полям и выполнение методов во время выполнения.
Элемент номер один уже был продемонстрирован выше с использованием
getClass()
для получения представления Person
во время выполнения
для доступа либо к полному, либо к простому имени класса в
модифицированной версии метода toString()
.
Второй элемент немного сложнее для создания примера, но это то, что
очень полезно для доступа к метаданным в классе. Некоторая информация,
которую вы можете запросить у экземпляра Class
- это такие вещи, как
конструкторы, поля и методы, а также другие вещи, такие как иерархии
наследования класса, такие как суперклассы и интерфейсы.
Примером этого является возможность использовать отладчики в среде IDE, например Eclipse и Netbeans, для просмотра членов и их значений в классе во время выполнения программы.
Возьмем, к примеру, следующее:
public class Main {
public static void main(String[] args) {
Person me = new Person("Adam", "McQuistan", LocalDate.parse("1987-09-23"));
Class c = me.getClass();
for (Field f : c.getDeclaredFields()) {
f.setAccessible(true);
try {
System.out.println(f.getName() + " = " + f.get(me));
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Выведет следующее:
firstName = Adam
lastName = McQuistan
dob = 1987-09-23
Опять же, ни один немазохист, вероятно, никогда бы не сделал этого в обычном повседневном программировании, но вы увидите, что такие вещи часто выполняются во фреймворках.
Заключение
В этой статье я описал значение и использование загадочного getClass()
класса Java Object. Я показал, как его можно использовать для получения
метаданных об экземпляре класса, таких как имя класса объекта во время
выполнения, а также объяснил, почему доступ к экземпляру класса может
быть полезен.
Как всегда, спасибо за чтение и не стесняйтесь комментировать или критиковать ниже.