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

在 Java 中,在选择使用 a.getClass()A.class时存在哪些利弊?两者都可以在需要 Class<?>的地方使用,但是我想在不同的情况下使用两者都会有性能或其他微妙的好处(就像使用 Class.forName()ClassLoader.loadClass()一样)。

47056 次浏览

我不会比较它们的优缺点,因为它们有不同的目的,很少有“选择”在两者之间。

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

  • A.class的计算结果为 A静止的,并且用于通常与反射相关的其他目的。

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


这篇文章已被改写为文章 给你

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

There may be a performance difference as well. While A.class can be resolved by the compiler because it knows the actual type of A, a.getClass() is a virtual method call happening at runtime.

作为参考,针对字节码的编译器通常为 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 不是 A 的实例,而是一个匿名子类的实例 的

a.getClass() requires an instance of type A

There is one difference i would like to add. Let us say you have a class a constructor as shown below with a super class which takes a Class object. You want that whenever a subclass object is created the subClass' class object should be passed to the super class. Below code will not compile as you cannot call an instance method in a constructor. In that case if you replace myObject.getClass() with MyClass.class. It will run perfectly.

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

当您有一个 class/type 的实例并希望获得它的确切类型时,可以使用 a.getClass。而当 type可用并且需要创建它的实例时,则使用 a.class
同时,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

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

The Output will be something like :

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

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语法