- Rukovodstvo
- статьи и идеи для разработчиков программного обеспечения и веб-разработчиков.
- Методы объектов Java: getClass ()
- Введение Эта статья является продолжением серии статей, описывающих часто забываемые методы базового класса Object языка Java. Ниже приведены методы базового объекта Java, присутствующие во всех объектах Java из-за неявного наследования объекта, а также ссылки на каждую статью этой серии. * toString [/ javas-object-methods-tostring /] * getClass (вы здесь) * равно [https://stackabuse.com/javas-object-methods-equals-object] * hashCode [https: // stackabuse. com /
- Вступление
- Метод getClass ()
- Для чего подходит объект класса?
- Заключение
- А знаете ли Вы, что возвращает .getClass()?
- 0. A.class vs a.getClass()
- 1. А что такое этот ваш Class?
- 2. А что же возвращает a.getClass()?
- 3. А что же написано в Object.java?
- Retrieving Class Objects
- Object.getClass()
- The .class Syntax
- Class.forName()
- TYPE Field for Primitive Type Wrappers
- Methods that Return Classes
Rukovodstvo
статьи и идеи для разработчиков программного обеспечения и веб-разработчиков.
Методы объектов Java: getClass ()
Введение Эта статья является продолжением серии статей, описывающих часто забываемые методы базового класса Object языка Java. Ниже приведены методы базового объекта Java, присутствующие во всех объектах Java из-за неявного наследования объекта, а также ссылки на каждую статью этой серии. * toString [/ javas-object-methods-tostring /] * getClass (вы здесь) * равно [https://stackabuse.com/javas-object-methods-equals-object] * hashCode [https: // stackabuse. com /
Вступление
Эта статья является продолжением серии статей, описывающих часто забываемые методы базового класса Object языка Java. Ниже приведены методы базового объекта Java, присутствующие во всех объектах Java из-за неявного наследования объекта, а также ссылки на каждую статью этой серии.
В центре внимания этой статьи — метод 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 ""; > >
Давайте сосредоточимся на переопределенном toString() , который перечисляет имя класса Person вместе со значениями полей экземпляра. Вместо «жесткого кодирования» имени класса Person в самой строке я мог бы фактически использовать метод getClass() для возврата экземпляра класса Class, который будет содержать эту информацию и позволит мне использовать ее как так:
Это приведет к замене исходного жестко запрограммированного текста «Person» на полное имя класса «com.adammcquistan.object.Person». Класс Class наполнен различными методами, которые позволяют идентифицировать все аспекты объекта класса, для которого был вызван getClass()
Например, если я хотел бы получить более упрощена toString() представление моего Person класса я мог бы просто поменять на c.getName() вызов с c.getSimpleName() , как показано ниже. Это, в свою очередь, вернет «Человек» вместо полного имени класса «com.adammcquistan.object.Person».
Основное различие в семантике использования 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. Я показал, как его можно использовать для получения метаданных об экземпляре класса, таких как имя класса объекта во время выполнения, а также объяснил, почему доступ к экземпляру класса может быть полезен.
Как всегда, спасибо за чтение и не стесняйтесь комментировать или критиковать ниже.
Licensed under CC BY-NC-SA 4.0
А знаете ли Вы, что возвращает .getClass()?
Я думаю, почти любого Java разработчика когда-то спрашивали на собеседовании: «Какие есть методы у класса Object?»
Меня, по крайней мере, спрашивали неоднократно. И, если в первый раз это было неожиданностью (кажется, забыл про clone), то потом я был уверен, что уж методы Object’а-то я знаю;)
И каково же было мое удивление, когда спустя несколько лет разработки я наткнулся на собственное незнание сигнатуры метода getClass()
Под катом пара слов про Class, .class, .getClass и, собственно, сюрприз, на который я наткнулся.
Итак, у нас есть класс А и объект этого класса a:
public class A < >. A a = new A();
0. A.class vs a.getClass()
Начнем с простого. При вызове getClass() может отработать полиморфизм, и результатом будет класс-потомок.
Тут была ложь, на которую мне указали в комментариях. class — это не статическое поле, коим может показаться (и даже не нативное-псевдо-статическое поле, как думал я), а особая конструкция языка. И, в отличие от статического поля, обратиться к нему через объект нельзя!
a.class; // Compile error! Unknown class: "a"
Но это так, цветочки. Идем дальше.
1. А что такое этот ваш Class?
public final class Class implements .
Это дженерик. Причем типизирован он, очевидно, этим самым A — классом, у которого вызвали .class
Если подумать, то понятно зачем это нужно: теперь, в частности, можно написать метод, который возвращает произвольный тип, в зависимости от аргумента:
2. А что же возвращает a.getClass()?
Действительно, ввиду полиморфизма нужно не забывать, что фактический класс объекта a — не обязательно A — это может быть любой подкласс:
Class result = a.getClass(); // Compilation successfull
3. А что же написано в Object.java?
Все эти дженерики — это, конечно, замечательно, но как записать сигнатуру метода getClass синтаксисом java в классе Object?
А никак:
public final native Class getClass();
The actual result type is Class where |X| is the erasure of the static type of the expression on which getClass is called.
Так что в Object.java написана одна сигнатура, а компилятор подставляет другую.
Retrieving Class Objects
The entry point for all reflection operations is java.lang.Class . With the exception of java.lang.reflect.ReflectPermission , none of the classes in java.lang.reflect have public constructors. To get to these classes, it is necessary to invoke appropriate methods on Class . There are several ways to get a Class depending on whether the code has access to an object, the name of class, a type, or an existing Class .
Object.getClass()
If an instance of an object is available, then the simplest way to get its Class is to invoke Object.getClass() . Of course, this only works for reference types which all inherit from Object . Some examples follow.
Class c = System.console().getClass();
There is a unique console associated with the virtual machine which is returned by the static method System.console() . The value returned by getClass() is the Class corresponding to java.io.Console .
enum E < A, B >Class c = A.getClass();
A is an instance of the enum E ; thus getClass() returns the Class corresponding to the enumeration type E .
byte[] bytes = new byte[1024]; Class c = bytes.getClass();
Since arrays are Objects , it is also possible to invoke getClass() on an instance of an array. The returned Class corresponds to an array with component type byte .
import java.util.HashSet; import java.util.Set; Set s = new HashSet(); Class c = s.getClass();
In this case, java.util.Set is an interface to an object of type java.util.HashSet . The value returned by getClass() is the class corresponding to java.util.HashSet .
The .class Syntax
If the type is available but there is no instance then it is possible to obtain a Class by appending «.class» to the name of the type. This is also the easiest way to obtain the Class for a primitive type.
boolean b; Class c = b.getClass(); // compile-time error Class c = boolean.class; // correct
Note that the statement boolean.getClass() would produce a compile-time error because a boolean is a primitive type and cannot be dereferenced. The .class syntax returns the Class corresponding to the type boolean .
Class c = java.io.PrintStream.class;
The variable c will be the Class corresponding to the type java.io.PrintStream .
The .class syntax may be used to retrieve a Class corresponding to a multi-dimensional array of a given type.
Class.forName()
If the fully-qualified name of a class is available, it is possible to get the corresponding Class using the static method Class.forName() . This cannot be used for primitive types. The syntax for names of array classes is described by Class.getName() . This syntax is applicable to references and primitive types.
Class c = Class.forName("com.duke.MyLocaleServiceProvider");
This statement will create a class from the given fully-qualified name.
Class cDoubleArray = Class.forName("[D"); Class cStringArray = Class.forName("[[Ljava.lang.String;");
The variable cDoubleArray will contain the Class corresponding to an array of primitive type double (that is, the same as double[].class ). The cStringArray variable will contain the Class corresponding to a two-dimensional array of String (that is, identical to String[][].class ).
TYPE Field for Primitive Type Wrappers
The .class syntax is a more convenient and the preferred way to obtain the Class for a primitive type; however there is another way to acquire the Class . Each of the primitive types and void has a wrapper class in java.lang that is used for boxing of primitive types to reference types. Each wrapper class contains a field named TYPE which is equal to the Class for the primitive type being wrapped.
There is a class java.lang.Double which is used to wrap the primitive type double whenever an Object is required. The value of Double.TYPE is identical to that of double.class .
Void.TYPE is identical to void.class .
Methods that Return Classes
There are several Reflection APIs which return classes but these may only be accessed if a Class has already been obtained either directly or indirectly.
Class.getSuperclass() Returns the super class for the given class.
Class c = javax.swing.JButton.class.getSuperclass();
The super class of javax.swing.JButton is javax.swing.AbstractButton . Class.getClasses() Returns all the public classes, interfaces, and enums that are members of the class including inherited members.
Class[] c = Character.class.getClasses();
Character contains two member classes Character.Subset and Character.UnicodeBlock . Class.getDeclaredClasses() Returns all of the classes interfaces, and enums that are explicitly declared in this class.
Class[] c = Character.class.getDeclaredClasses();
import java.lang.reflect.Field; Field f = System.class.getField("out"); Class c = f.getDeclaringClass();
public class MyClass < static Object o = new Object() < public void m() <>>; static Class = o.getClass().getEnclosingClass(); >
The declaring class of the anonymous class defined by o is null . Class.getEnclosingClass() Returns the immediately enclosing class of the class.
Class c = Thread.State.class().getEnclosingClass();
public class MyClass < static Object o = new Object() < public void m() <>>; static Class = o.getClass().getEnclosingClass(); >