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

在Java中,围绕使用a.getClass()A.class的select存在哪些优点/缺点? 任何一个都可以在任何需要Class<?>地方使用,但是我想在不同情况下使用这两个方法会有性能或者其他微妙的好处(就像Class.forName()ClassLoader.loadClass()

我不会比较他们的利弊,因为他们有不同的目的,而且两者之间很less有“select”。

  • a.getClass()返回a的运行时types 。 也就是说,如果你有A a = new B(); 那么a.getClass()将返回B类。

  • A.class 静态地评估A类,并被用于通常与reflection有关的其他目的。

在性能方面, 可能会有一个可测量的差异,但是我不会说这些,因为最终它是依赖于JVM和/或编译器的。


这篇文章在这里被重写为一篇文章。

他们实际上是不同的,在哪里可以使用它们。 A.class在编译时工作,而a.getClass()需要Atypes的实例并在运行时工作。

也可能有性能差异。 虽然A.class可以由编译器parsing,因为它知道A的实际types,但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依赖,但是。

看看下面的例子

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

a.getClass()需要一个types为A的实例

当你有一个类/types的实例,并且你想得到它的确切types时,使用a.getClass 。 而type可用时则使用a.class并且要创build它的实例。
另外, getClass()返回实例的运行时types,而.class则是在编译时计算的。
考虑到getClass().class性能, .classgetClass()有更好的性能。
例如:

 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 

有趣的是,上面例子中提到的性能差异似乎与其他原因有关。 使用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 

我想添加一个区别。 让我们说你有一个类的构造函数,如下所示的一个超类,它需要一个类对象。 每当创build子类对象时,都希望子类的类对象应该传递给超类。 下面的代码不会编译,因为您不能在构造函数中调用实例方法。 在这种情况下,如果你用MyClass.classreplacemyObject.getClass() 。 它将完美运行。

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