¿Cuál es la diferencia entre a.getClass () y A.class en Java?

En Java, ¿qué pros / contra existen en torno a la elección de utilizar a.getClass() o A.class ? Cualquiera de los dos puede usarse donde se espere una Class , Pero imagino que habría beneficios de rendimiento u otros para sutilizar el uso de ambos en diferentes circunstancias (como Class.forName() con Class.forName() y ClassLoader.loadClass() .

No los compararía en términos de pros / contra, ya que tienen diferentes propósitos y rara vez hay una “opción” para hacer entre los dos.

  • a.getClass() devuelve el tipo de tiempo de ejecución de a . Es decir, si tiene A a = new B(); entonces a.getClass() devolverá la clase B

  • A clase A.class evalúa estáticamente en la clase A y se usa para otros fines a menudo relacionados con la reflexión.

En términos de rendimiento, puede haber una diferencia medible, pero no diré nada al respecto porque al final depende de JVM y / o del comstackdor.


Esta publicación ha sido reescrita como un artículo aquí .

En realidad, son diferentes con respecto a dónde puedes usarlos. A.class funciona en tiempo de comstackción, mientras que a.getClass() requiere una instancia de tipo A y funciona en tiempo de ejecución.

Puede haber una diferencia de rendimiento también. Mientras que A.class puede ser resuelto por el comstackdor porque conoce el tipo real de A , a.getClass() es una llamada de método virtual que ocurre en el tiempo de ejecución.

Como referencia, un comstackdor de código de byte normalmente emite las siguientes instrucciones para Integer.getClass() :

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

y lo siguiente para Integer.class :

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

El primero normalmente implica un despacho de método virtual y, por lo tanto, presumiblemente tarda más tiempo en ejecutarse. Sin embargo, eso es, al final, dependiente de JVM.

eche un vistazo a los ejemplos a continuación

a.getClass()!= A.class , es decir, a no es una instancia de A, sino de una subclase anónima de A

a.getClass() requiere una instancia de tipo A

Use a.getClass cuando tenga una instancia de clase / tipo y desee obtener el tipo exacto de la misma. mientras que a.class se usa cuando tiene el type disponible y desea crear una instancia del mismo.
También getClass() devuelve el tipo de instancia en tiempo de ejecución mientras que .class se evalúa en tiempo de comstackción.
Teniendo en cuenta el rendimiento de getClass() y .class , .class tiene un mejor rendimiento que getClass() .
Ejemplo:

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

Salida:

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

Hay una diferencia que me gustaría agregar. Digamos que tiene una clase un constructor como se muestra a continuación con una súper clase que toma un objeto Clase. Desea que siempre que se cree un objeto de subclase, el objeto de clase subClass se pase a la superclase. A continuación, el código no se comstackrá ya que no puede llamar a un método de instancia en un constructor. En ese caso, si reemplaza myObject.getClass() con MyClass.class . Funcionará perfectamente.

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

Curiosamente, las diferencias de rendimiento mencionadas en el ejemplo anterior parecen estar relacionadas con otras razones. Usando 3 clases diferentes, en promedio el rendimiento será casi el mismo:

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

La salida será algo así como:

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

Y cambiar el orden de las llamadas incluso hará que getClass() sea ​​más rápido.

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

Salida:

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