що таке об’єкт Class (java.lang.Class)?


82

У документації Java для Classсказано:

ClassОб'єкти будуються автоматично віртуальною машиною Java при завантаженні класів та викликах defineClassметоду в завантажувачі класів.

Що це за Classпредмети? Вони однакові з об'єктами, створеними з класу за допомогою виклику new?

Крім того, наприклад, object.getClass().getName()як можна все ввести для суперкласу Class, навіть якщо я не успадковую від java.lang.Class?

Відповіді:


97

Ніщо не отримує друку Class. Кожне Objectв Java належить певному class. Ось чому Objectклас, який успадковується усіма іншими класами, визначає getClass()метод.

getClass(), або class-literal - Foo.classповертає Classоб'єкт, який містить деякі метадані про клас:

  • ім'я
  • пакет
  • методи
  • поля
  • конструктори
  • анотації

і деякі корисні методи , такі як лиття і різних перевірки ( isAbstract(), isPrimitive()і т.д.). javadoc показує, яку саме інформацію ви можете отримати про клас.

Отже, наприклад, якщо вашому методу дано об’єкт, і ви хочете обробити його на випадок, якщо він анотований @Processableанотацією, то:

public void process(Object obj) {
    if (obj.getClass().isAnnotationPresent(Processable.class)) {
       // process somehow; 
    }
}

У цьому прикладі ви отримуєте метадані про клас даного об’єкта (яким би він не був) і перевіряє, чи має він дану анотацію. Багато методів на Classекземплярі називаються "відображаючими операціями" або просто "відображенням". Прочитайте тут про відображення, чому і коли воно використовується.

Також зверніть увагу, що Classоб’єкт представляє перелічення та інтерфейси разом із класами в запущеному додатку Java і має відповідні метадані.

Підводячи підсумок - кожен об’єкт у Java має (належить) клас і має відповідний Classоб’єкт, який містить про нього метадані, доступні під час виконання.


37
І цікаво думати про це далі. ClassКлас успадковує від Objectсебе. Class.classповертає Classоб'єкт, що представляє Classклас. Ви можете розмірковувати над роздумами. МОЯ ГОЛОВА АСПЛОД.
cdhowie

1
@pst: Я маю. Мені хочеться нашкодити людям. Будь-яка мова / фреймворк із багатьма методами кореневого типу заслуговує на поховання. Він має синдром випадкового придурювання до API-інтерфейсу без будь-якого передбачення. Cue the flames ...
cdhowie

1
Клас c1 = Car.class; Що це за "клас"? це відкрита змінна, яка існує у кожному класі?
david blaine

1
Певним чином, так. Насправді це "літерал класу" - саме таким чином ви посилаєтесь на об'єкт класу за іменем.
Божо

1
@cdhowie Ваш коментар для мене семантично наситив слово "клас".
stillanoob

44

Об'єкт Class - це свого роду мета-об'єкт, що описує клас об'єкта. Він використовується переважно з можливостями відображення Java. Ви можете сприймати це як "план" власне класу. Наприклад, у вас є такий клас автомобіля:

public class Car {
    public String brand;
}

Потім ви можете побудувати об’єкт Class, який описує ваш клас "Car".

Class myCarClass = Class.forName("Car");

Тепер ви можете робити всілякі запити щодо вашого класу Car щодо цього об’єкта Class:

myCarClass.getName() - returns "Car"
myCarClass.getDeclaredField("brand") - returns a Field object describing the "brand" field

і так далі. Кожен об'єкт Java має метод getClass (), який повертає об'єкт Class, що описує клас об'єкта Java. Тож ви можете зробити щось на зразок:

Car myCar = new Car();
Class myCarClass  = myCar.getClass();

Це також працює для об’єктів, яких ви не знаєте, наприклад, об’єктів, які ви отримуєте ззовні:

public void tellMeWhatThisObjectsClassIs(Object obj) {
    System.out.println(obj.getClass().getName());
}

Ви можете подати цей метод будь-якому об'єкту Java, і він буде друкувати фактичний клас об'єкта, який ви йому надали.

Працюючи з Java, більшу частину часу не потрібно турбуватися про об’єкти класу. У них є кілька зручних випадків використання. Наприклад, вони дозволяють програмно інстанціювати об'єкти певного класу, який часто використовується для серіалізації та десеріалізації об'єктів (наприклад, перетворення об'єктів Java вперед і назад у / з XML або JSON).

Class myCarClass = Class.forName("Car");
Car myCar = myCarClass.newInstance();  // is roughly equivalent to = new Car();

Ви також можете скористатися ним, щоб дізнатись усі заявлені поля чи методи вашого класу тощо, що дуже корисно в певних випадках. Так, наприклад, якщо ваш метод отримує невідомий об’єкт, і ви повинні знати про нього більше, наприклад, якщо він імплементує якийсь інтерфейс тощо, клас Class - ваш друг тут.

Коротше кажучи, класи, поле, метод тощо, що знаходяться в пакеті java.lang.reflect, дозволяють аналізувати визначені класи, методи, поля, створювати нові їх екземпляри, викликати методи всіляких інших речей і вони дозволяють робити це динамічно під час виконання.


1
Клас c1 = Car.class; Що це за "клас"? це відкрита змінна, яка існує у кожному класі?
david blaine

5
В основному це синтаксичний цукор. Це те, що компілятор оцінює до чогось, що завантажує об’єкт класу із заданим ім’ям. Приблизно еквівалентно Class.forName ("повністю кваліфіковане ім'я класу"), але клас перевіряється на існування під час компіляції, тоді як Class.forName () виконується під час виконання.
Ян Тома,

8

getClass()є методом, який повертає об'єкт, який є екземпляром java.lang.Class... не проводиться кастинг. Кастинг виглядав би так:

Class<?> type = (Class<?>) object;

7

Я також хотів би додати до відповіді ColinD, що getClass поверне той самий об'єкт для екземплярів одного типу. Це надрукує true :

    MyOtherClass foo = new MyOtherClass();
    MyOtherClass bar = new MyOtherClass();
    System.out.println(foo.getClass()==bar.getClass());

Зауважте, що це не так equals, я використовую ==.


3

Об'єкт класу є екземпляром класу (java.lang.Class). Нижче цитата з класу Javadoc повинна відповісти на ваше запитання

Клас не має публічного конструктора. Натомість об’єкти класу автоматично будуються віртуальною машиною Java під час завантаження класів та викликами методу defineClass у завантажувачі класів.


2

Для того, щоб повністю зрозуміти об’єкт класу, поверніться назад і зрозумійте, що спочатку ми отримуємо об’єкт класу. Розумієте, кожен .javaфайл, який ви створюєте, при компіляції цього .javaфайлу jvm створює .classфайл, цей файл містить всю інформацію про клас, а саме:

  1. Повна назва класу
  2. Батько класу
  3. Інформація про метод
  4. Змінні поля
  5. Конструктор
  6. Інформація про модифікатор
  7. Постійний басейн

Список, який ви бачите вище - це те, що ви зазвичай бачите в типовому класі. Тепер, до цього моменту, ваш .javaфайл і .classфайл існують на вашому жорсткому диску, коли вам насправді потрібно використовувати клас, тобто виконати код у main()методі, jvm використає цей .classфайл на вашому жорсткому диску і завантажить його в одну з 5 пам’яті області в jvm, яка є областю методу, відразу після завантаження .classфайлу в область методу, jvm використовуватиме цю інформацію та об'єкт Class, який представляє той клас, який існує в області пам'яті купи.

Ось вид верхнього рівня,

.java--compile -> .class-> під час виконання вашого сценарію -> .classзавантаження в область методу - jvm створює об'єкт класу з області методу -> народжується об'єкт класу

За допомогою об’єкта класу ви отримуєте таку інформацію, як ім’я класу та імена методів, все про клас.

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

Сподіваюся, це має сенс


хороші додаткові бали. одне зауваження до формулювання, я не знаю тему, яку корисно редагувати самому, "jvm використовуватиме цю інформацію та об'єкт класу, який представляє той клас, який існує в області пам'яті купи". виглядає неправильно, рядок пізніше з -> виглядає більш логічним. Я тут? будь ласка, будьте послідовними, дякую!
Олексій Мартьянов

@Brendon Cheung, коли ви сказали "об'єкт класу, який представляє цей клас" , це клас, а не екземпляр цього класу, тому я думаю, що нам слід змінити вираз. Оскільки лише «екземпляри» потрапляють у пам’ять купи, а не їх клас.
starriet

1

Клас Object є батьківським класом усіх класів у Java за замовчуванням. Іншими словами, це найвищий клас Java.

Клас Object є корисним, якщо ви хочете посилатися на будь-який об'єкт, тип якого ви не знаєте. Зверніть увагу, що посилальна змінна батьківського класу може посилатися на об'єкт дочірнього класу, відомий як оновлення.

Давайте візьмемо приклад, є метод getObject (), який повертає об’єкт, але він може бути будь-якого типу, наприклад, Employee, Student тощо, ми можемо використовувати посилання на клас Object для посилання на цей об’єкт. Наприклад:

Object obj=getObject(); // ми не знаємо, який об’єкт буде повернено з цього методу

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.