Java中的getClass如何工作

时间:2015-10-03 05:04:34

标签: java object tostring

以下是JavaDoc所说的内容:

public final Class <?> getClass()
     

返回此Object的运行时类。返回的Class对象是由所表示的类的static synchronized方法锁定的对象   实际结果类型为Class<? extends |X|>,其中|X|是要调用getClass的表达式的静态类型的擦除。例如,不需要强制转换在此代码片段中:

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

返回:
    Class对象,表示此对象的运行时类。

现在,我知道它是一种本机方法,因此它是在依赖于平台的代码中实现的。但是这种方法的返回类型呢。

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() returns a class, how come I can get a string too?
  3. 注释代码,否则会导致编译时错误。

3 个答案:

答案 0 :(得分:7)

每个对象的数据包含对类java.lang.Class的对象的引用,这由方法getClass返回。还有一个描述java.lang.Class的java.lang.Class对象。

将Class对象视为&#34;蓝图&#34;描述正在制作对象的某个类。按理说,蓝图也需要自己的蓝图(否则工程师将如何知道如何制作蓝图)。

这些陈述试图说明这一点。

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()方法,并返回类&#39; 名称的。如果您想要打印类的所有细节(类似于打印蓝图本身),您必须编写大量代码 - 只需查看java.lang.Class的javadoc即可:需要检索大量信息(如蓝图所示)。

答案 1 :(得分:1)

此时,我们需要区分该类型的typeinstance。让我们用一个例子来解释它。

    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.lang.Object,它们都没有超类)
  • 类型是类还是接口
  • 类型的修饰符(“public,abstract,final”的某个子集)
  • 任何直接超接口的完全限定名称的有序列表

<强>实例

instaneOfA是对类型A的实际实例的引用,它指向堆内存中的地址。

getClass()的返回类型是通用Class类型。与java中可用的许多其他type - 字符串,整数等一样,Class也是表示相关类型信息的类型。

toString()方法在Dog类的instance上关联并调用,而不是在Dog类型本身上。

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

这是由于在将右侧的表达式结果分配给左手侧(不是同一类型)时发生类型不匹配。 类dd指的是类类型的引用。 狗是完全不同的类型,并且可以将新的Dog()分配给“Dog”类型的引用。

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

答案 2 :(得分:0)

我对你的问题3有答案,

这会产生编译时错误,因为

原因1:对于Class实例,您只能分配表示Dog类的类对象,但不能直接分配Dog类对象。

例如:Class dd = Dog.class或Class dd = Class.forName(“Dog”); 是正确的语法。

原因2:类Class是最终类,但不是Dog类的超类。回到java中动态方法分派的概念,你只能将子类对象分配给超类变量。