2012-06-08 23 views
87

En Java, ¿qué pros/contra existen en torno a la opción de usar a.getClass() o A.class? Cualquiera puede ser utilizado donde se espera un Class<?>, pero me imagino que no habría rendimiento u otros beneficios sutiles que utilizan tanto en diferentes circunstancias (al igual que hay con Class.forName() y ClassLoader.loadClass().¿Cuál es la diferencia entre a.getClass() y A.class en Java?

Respuesta

138

no me compararlos en términos de ventajas/desventajas, ya que tienen diferentes propósitos y hay rara vez una "opción" para que entre los dos.

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

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

En términos de rendimiento, no puede haber una diferencia medible, pero no voy a decir nada al respecto, porque al final es JVM y/o compilador dependiente.


Esta publicación se ha reescrito como artículo here.

+0

¿Qué 'A.class.getClass()'? – user1870400

+0

Eso le daría el objeto 'Clase' de la clase que representa el objeto' A.class' que es nuevamente una instancia de 'java.lang.Class'. – aioobe

30

En realidad, son diferentes en cuanto a dónde se puede usar. A.class funciona en tiempo de compilación, mientras que a.getClass() requiere una instancia de tipo A y funciona en tiempo de ejecución.

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

Para referencia, un código de bytes compilador orientación típicamente emite las siguientes instrucciones de Integer.getClass():

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

y la siguiente para Integer.class:

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

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

El primero sería típicamente implicar un método de despacho virtual y por lo tanto presumiblemente tomar más tiempo para ejecutar. Sin embargo, eso es, al final, dependiente de JVM.

+1

[1] técnicamente, la Especificación del lenguaje Java no menciona ningún grupo constante en absoluto ... – aioobe

+0

@aioobe: Supongo que tiene razón, es por eso que revisé el bytecode generado por Sun JDK. –

+1

... que técnicamente tampoco proporciona una respuesta autorizada, ya que la Especificación del lenguaje Java ni siquiera menciona bytecode cuando se trata de semántica. – aioobe

5

echar un vistazo a los ejemplos a continuación

a.getClass()!= A.class, es decir, un no es una instancia de una sino de una clase de sub anónimo de A

a.getClass() requiere una instancia de tipo A

1

Hay es 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 compilará 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 
    } 
} 
+2

Tener una instancia de la misma clase que las variables de instancia de la misma clase ... Se quedará sin espacio en el montón mientras crea objetos recursivamente. –

4

Uso a.getClass cuando se tiene una instancia de la clase/tipo y desea obtener el tipo exacto de la misma. mientras que a.class se usa cuando tiene type disponible y desea crear una instancia de este.
También getClass() devuelve el tipo de instancia en tiempo de ejecución mientras que .class se evalúa en tiempo de compilació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"); 
    } 

} 

de salida:

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

Curiosamente las diferencias en el rendimiento mencionados en el ejemplo anterior, parece estar relacionado a otras razones. El uso de 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 la conmutación del orden de las llamadas será incluso dar lugar a getClass() ser 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 
+0

"Usar 3 clases diferentes". Pero en la sección getClass() no estás usando 3 clases diferentes. Estos son todos String y, por lo tanto, getClass devolverá java.lang.String para todas las instancias. – John

Cuestiones relacionadas