Java中的a.getClass()和A.class有什么区别?

时间:2012-06-08 11:13:59

标签: java class reflection

在Java中,使用a.getClass()A.class的选择存在哪些优缺点?可以在期望Class<?>的任何地方使用,但我想在不同情况下使用它们会有性能或其他微妙的好处(就像Class.forName()ClassLoader.loadClass()一样。

7 个答案:

答案 0 :(得分:152)

我不会在利弊方面对它们进行比较,因为它们有不同的目的,而且两者之间很少有“选择”。

  • a.getClass()返回a运行时类型。即,如果您有A a = new B();,则a.getClass()将返回B类。

  • A.class评估为A静态,并用于与反射相关的其他目的。

就性能而言,可能是一个可衡量的差异,但我不会说任何关于它的事情,因为最终它依赖于JVM和/或编译器。


此帖子已被重写为文章here

答案 1 :(得分:32)

它们实际上与您可以使用它们的方式不同。 A.class在编译时工作,而a.getClass()需要类型为A的实例,并且在运行时工作。

也可能存在性能差异。虽然A.class可以由编译器解析,因为它知道A的实际类型,a.getClass()是在运行时发生的虚方法调用。

作为参考,针对字节码的编译器通常会发出Integer.getClass()的以下说明:

aload_1
invokevirtual   #3; //Method java/lang/Object.getClass:()Ljava/lang/Class;

以及Integer.class的以下内容:

//const #3 = class  #16;    //  java/lang/Integer

ldc_w   #3; //class java/lang/Integer

前者通常涉及虚拟方法调度,因此可能需要更长的时间来执行。然而,这最终取决于JVM。

答案 2 :(得分:6)

看看下面的例子

a.getClass()!= A.class,即a不是A的实例,而是匿名子类的实例 一个

a.getClass()需要A类型的实例

答案 3 :(得分:4)

如果您有类/类型的实例,并且想要获得它的确切类型,请使用a.getClass。当a.class可用且您想要创建它的实例时使用type
此外,getClass()返回实例的运行时类型,而.class在编译时进行评估 考虑到getClass().class的效果,.class的效果优于getClass()
示例:

public class PerfomanceClass {

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        long time=System.nanoTime();
        Class class1="String".getClass();
        class1="String".getClass();
        class1="String".getClass();
        class1="String".getClass();

        System.out.println("time (getClass()) :"+(System.nanoTime()-time)+" ns");     


        long time2=System.nanoTime();
        Class class2=String.class;
        class2=String.class;
        class2=String.class;
        class2=String.class;

        System.out.println("time (.class):"+(System.nanoTime()-time2)+" ns");
    }

}

输出:

time (getClass()) : 79410 ns
time (.class)     : 8032 ns

答案 4 :(得分:1)

我想添加一个区别。让我们假设你有一个类构造函数,如下所示,带有一个带有Class对象的超类。您希望无论何时创建子类对象,都应将subClass的类对象传递给超类。下面的代码将无法编译,因为您无法在构造函数中调用实例方法。在这种情况下,如果您将myObject.getClass()替换为MyClass.class。它将完美运行。

Class MyClass
{
    private MyClass myObject = new MyClass();
    public MyClass()
    {
        super(myObject.getClass()); //error line compile time error
    }
}

答案 5 :(得分:0)

有趣的是,上面例子中提到的性能差异似乎与其他原因有关。使用3个不同的类,平均性能几乎相同:

import java.util.LinkedHashMap;
public class PerfomanceClass {

public static void main(String[] args) {

    long time = System.nanoTime();
    Class class1 = "String".getClass();
    Class class11 = "Integer".getClass();
    Class class111 = "LinkedHashMap".getClass();

    System.out.println("time (getClass()) :" + (System.nanoTime() - time) + " ns");

    long time2 = System.nanoTime();
    Class class2 = String.class;
    Class class22 = Integer.class;
    Class class222 = LinkedHashMap.class;

    System.out.println("time (.class):" + (System.nanoTime() - time2) + " ns");
} }

输出将类似于:

time (getClass()) :23506 ns 
time (.class):23838 ns

切换通话顺序甚至会导致getClass()更快。

import java.util.LinkedHashMap;

public class PerfomanceClass {

public static void main(String[] args) {
    long time2 = System.nanoTime();
    Class class2 = LinkedHashMap.class;

    System.out.println("time (.class):" + (System.nanoTime() - time2) + " ns");

    long time = System.nanoTime();
    Class class1 = "LinkedHashMap".getClass();

    System.out.println("time (getClass()) :" + (System.nanoTime() - time) + " ns");
}}

输出:

time (.class):33108 ns
time (getClass()) :6622 ns

答案 6 :(得分:0)

p.getClass(),其中p是对象的实例,返回该对象p的运行时类。 p不能是会导致编译时错误的类型,它应该是对象的实例。

// B extends A
A a = new B();
System.out.println(a.getClass());
//output: class B

p.class是一个表达式。 .class被称为类语法。 p是一种类型。它可以是类,接口或数组的名称,甚至可以是原始类型的名称。 a.getClass() == B.class

如果类型可用并且有实例,则可以使用getClass方法获取类型的名称。否则,请使用.class语法