Как работает getClass в Java

вот что JavaDoc говорит:

public final Class <?> getClass()

возвращает класс выполнения этого Object. Вернувшийся Class объект-это объект, который заблокирован static synchronized методы представленного класса.
фактический тип результата Class<? extends |X|> здесь |X| - это стирание статического типа выражения, на котором getClass называется. например, в этом фрагменте кода не требуется приведение:

Number n = 0;
Class<? extends Number> c = n.getClass();

возвращает:
Объект класса, представляющий класс среды выполнения этого объекта.

теперь я понимаю, что это собственный метод, поэтому он реализован в зависящем от платформы коде. Но как насчет возвращаемого типа этого метода?

public final Class<?> getClass()

кроме того, рассмотрим код:

class Dog
{
    @Override
    public String toString()
    {
        return "cat";
    }
}

public class Main
{
    public static void main(String[] args)
    {
        Dog d= new Dog();
        //Class<Dog> dd = new Dog();  Compile time error
        System.out.println(d.getClass());
    }
}

выход:

собака класс

Итак, мой вопрос заключается в :

  1. тип возврата этого метода
  2. метод toString не вызывается . Подобный пост на эту тему : Java. getClass () возвращает класс, как я могу получить строку тоже?
  3. прокомментированный код, который в противном случае дает ошибку времени компиляции.

3 ответов


данные для каждого объекта содержат ссылку на объект класса java.ленг.Class, и это возвращается методом getClass. Существует также одна java.ленг.Объект класса, описывающий java.ленг.Класс.

подумайте об объекте класса как о "схеме", описывающей определенный класс, из которого создаются объекты. Само собой разумеется, что чертежи также нуждаются в своем собственном проекте (или иначе, как инженеры знают, как делать чертежи).

эти операторы пытаются проиллюстрировать это.

Integer integer = 1;
Class<?> clazzInteger = integer.getClass();
System.out.println( "class of integer=" + clazzInteger );
Class<?> clazzClazzInteger = clazzInteger.getClass();
System.out.println( "class of class Integer's class=" + clazzClazzInteger );
String string = "x";
Class<?> clazzString = string.getClass();
System.out.println( "class of string=" + clazzString );
Class<?> clazzClazzString = clazzString.getClass();
System.out.println( "class of class String's class=" + clazzClazzString );

выход:

class of integer=class java.lang.Integer
class of class Integer's class=class java.lang.Class
class of string=class java.lang.String
class of class String's class=class java.lang.Class

класс имеет имя, как и все, что описывается чертежом, имеет имя, которое не следует путать с самим чертежом. Если объект класса появляется в определенном контексте, его метод toString () вызывается неявно, и это возвращает класс' имя. Если вы хотите напечатать все мелкие детали класса (сродни печати самого чертежа), вам придется написать много кода - просто посмотрите на javadoc для Java.ленг.Класс: нужно извлечь очень много информации (как и подобает чертежу).


на данный момент нам нужно различать type и instance типа. Давайте объясним это на примере.

    public class A {
        public static void main(String[] args) {
            Class<A> typeInformation = A.class; //Type information associated with type `A`
            A instanceOfA = new A();  //actual instance of type `A`
        }   
    }

тип

ссылка "typeInformation" в приведенном выше коде имеет тип Class сохраняя в стороне дженерики на некоторое время. Эта информация обычно проживающих в куче память. Следующая информация хранится против каждого из type загрузка jvm:

  • в полное имя типа
  • полное имя прямого суперкласса типа (если тип не является интерфейсом или классом java.ленг.Объекта, ни один из которых не имеет суперкласса)
  • является ли тип классом или интерфейсом
  • модификаторы типа (некоторое подмножество` public, abstract, final)
  • упорядоченный список полных имен любых прямых суперинтерфейсов

экземпляр

instaneOfA является ссылкой на фактический экземпляр типа A, который указывает на адрес в памяти.

возвращаемый тип getClass () является общим Class тип. Как и многие другие types доступно в java-String, Integer etc, Class также является типом, представляющим связанную информацию о типе.

метод toString () связан и вызывается на instance класса собак, не на самом Собачьем типе.

//Class<Dog> dd = new Dog(); Compile time error

это связано с несоответствием типа, возникающим при назначении результата выражения в правой части левой стороне, которая не имеет того же типа. Класс dd ссылается на ссылку типа класса. Собака-это совершенно другой тип, и новая собака() может быть назначена ссылке типа "собака".

эта ссылка поможет вам понять аспекты проектирования Java runtime среды


У меня есть ответ на ваш вопрос 3,

Это дает ошибку времени компиляции, потому что

Причина 1: для экземпляра класса можно назначить только объект класса, представляющий класс Dog, но нельзя назначить объект класса Dog напрямую.

например: класс dd=Dog.класс или класс dd=класс.forName("собака"); является правильным синтаксисом.

Причина 2: класс класса является окончательным классом, но не супер-классом для класса собаки. Вернуться к концепции динамический метод dispatch в java, где вы можете назначить только объекты подкласса переменной суперкласса.