How does getClass in Java work

送分小仙女□ 提交于 2019-12-03 09:40:28

问题


Here is what JavaDoc says:

public final Class <?> getClass()

Returns the runtime class of this Object. The returned Class object is the object that is locked by static synchronized methods of the represented class.
The actual result type is Class<? extends |X|> where |X| is the erasure of the static type of the expression on which getClass is called. For example, no cast is required in this code fragment:

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

Returns:
The Class object that represents the runtime class of this object.

Now , I understand it is a native method , so it is is implemented in platform-dependent code. But what about the return type of this method.

public final Class<?> getClass()

Also , consider the code:

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());
    }
}

Output:

class Dog

So, my query lies in :

  1. Return type of this method
  2. toString method is not called . A similar post on this topic is : Java. getClass() returns a class, how come I can get a string too?
  3. The commented code which otherwise give compile time error.

回答1:


The data for each object contains a reference to an object of class java.lang.Class, and this is returned by the method getClass. There is also one java.lang.Class object describing java.lang.Class.

Think of a Class object as the "blueprint" describing a certain class from which objects are being made. It stands to reason that blueprints also need a blueprint of their own (or else how would engineers know how to make blueprints).

These statements try to illustrate this.

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 );

Output:

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

A class has a name, just like anything described by a blueprint has a name which is not to be confused with the blueprint itself. If a class object appears in a certain context, its toString() method is called implicitly, and this returns the class' name. If you'd like to print all the nitty-gritty details of a class (akin to printing the blueprint itself) you'd have to write a lot of code - just look at the javadoc for java.lang.Class: there's an awful lot of information to be retrieved (as befits a blueprint).




回答2:


At this point, we need to differentiate between a type and an instance of the type. Lets explain it with an example.

    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`
        }   
    }

Type

The reference 'typeInformation' in the above code is of the type Class keeping aside the generics for a while. This information will typically be residing in non-heap memory section. Following information is store against each of the type jvm loads :

  • The fully qualified name of the type
  • The fully qualified name of the type's direct superclass (unless the type is an interface or class java.lang.Object, neither of which have a superclass)
  • Whether or not the type is a class or an interface
  • The type's modifiers ( some subset of` public, abstract, final)
  • An ordered list of the fully qualified names of any direct superinterfaces

Instance

instaneOfA is a reference to the actual instance of the type A which points to an address in the heap memory.

Return type of getClass() is a generic Class type. Like many other types available in java - String, Integer etc, Class is also a type representing the type information associated.

toString() method is associated and invoked on an instance of the Dog class, not on the Dog type itself.

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

This is due to Type mismatch occuring while assigning the result of expression in the right hand side to the Left Hand Side, which is not of the same type. Class dd refers to a reference of Class type. Dog is a different type altogether, and a new Dog() can be assigned to a reference of the type 'Dog'.

This link will help you understand the design aspects of java runtime environment




回答3:


I have an answer for your Question 3,

This gives compile time error because

Reason 1: For a Class instance, You can only assign class object that represents the Dog class, but you can't assign the Dog class object directly.

For example: Class dd=Dog.class or Class dd=Class.forName("Dog"); is correct syntax.

Reason 2: The class Class is a final class but not a super class for Dog class. You go back to the concept of dynamic method dispatch in java,where you can only assign subclass objects to a superclass variable.



来源:https://stackoverflow.com/questions/32919106/how-does-getclass-in-java-work

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!