web-dev-qa-db-fra.com

Quelle est la différence entre a.getClass () et A.class en Java?

Dans Java quels avantages/inconvénients existent autour du choix d'utiliser a.getClass() ou A.class? Soit peut être utilisé partout où un Class<?> Est attendu , mais j'imagine qu'il y aurait des performances ou d'autres avantages subtils à utiliser les deux dans des circonstances différentes (tout comme il y en a avec Class.forName() et ClassLoader.loadClass().

97
IAmYourFaja

Je ne les comparerais pas en termes d'avantages/inconvénients car ils ont des objectifs différents et il y a rarement un "choix" à faire entre les deux.

  • a.getClass() renvoie le type d'exécution de a. C'est-à-dire que si vous avez A a = new B(); alors a.getClass() renverra la classe B.

  • A.class correspond à la classe Astatiquement, et est utilisé à d'autres fins souvent liées à la réflexion.

En termes de performances, il y a peut-être une différence mesurable, mais je ne dirai rien à ce sujet car au final, cela dépend de la JVM et/ou du compilateur.


Ce message a été réécrit en tant qu'article ici .

155
aioobe

Ils sont en fait différents quant à l'endroit où vous pouvez les utiliser. A.class Fonctionne à la compilation tandis que a.getClass() requiert une instance de type A et fonctionne à l'exécution.

Il peut également y avoir une différence de performances. Alors que A.class Peut être résolu par le compilateur car il connaît le type réel de A, a.getClass() est un appel de méthode virtuelle se produisant au moment de l'exécution.

Pour référence, un compilateur ciblant le bytecode émet généralement les instructions suivantes pour Integer.getClass():

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

et ce qui suit pour Integer.class:

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

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

Le premier impliquerait généralement une répartition de méthode virtuelle et, par conséquent, prendrait probablement plus de temps à exécuter. Cependant, cela dépend de la JVM.

32

jetez un œil aux exemples ci-dessous

a.getClass()!= A.class, c'est-à-dire que a n'est pas une instance de A mais d'une sous-classe anonyme de A

a.getClass() nécessite une instance de type A

6

Utilisez a.getClass Lorsque vous avez une instance de classe/type et que vous souhaitez obtenir le type exact de celle-ci. tandis que a.class est utilisé lorsque vous disposez de type et que vous souhaitez en créer une instance.
getClass() renvoie également le type d'instance d'exécution tandis que .class Est évalué au moment de la compilation.
Compte tenu des performances de getClass() et .class, .class A de meilleures performances que getClass().
Exemple:

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

}

Sortie:

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

Il y a une différence que j'aimerais ajouter. Disons que vous avez une classe un constructeur comme indiqué ci-dessous avec une super classe qui prend un objet Class. Vous voulez que chaque fois qu'un objet de sous-classe est créé, l'objet de classe de la sous-classe doit être passé à la super classe. Le code ci-dessous ne se compilera pas car vous ne pouvez pas appeler une méthode d'instance dans un constructeur. Dans ce cas, si vous remplacez myObject.getClass() par MyClass.class. Il fonctionnera parfaitement.

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

p.getClass(), où p est une instance d'un objet, retourne la classe d'exécution de cet objet p. p ne peut pas être un type qui provoquera une erreur de compilation, il doit s'agir d'une instance d'un objet.

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

p.class Est une expression. Le .class Est appelé la syntaxe de classe. p est un type. Il peut s'agir du nom d'une classe, d'une interface ou d'un tableau et même d'un type primitif. a.getClass() == B.class.

Si un type est disponible et qu'il existe une instance, il est possible d'utiliser la méthode getClass pour obtenir le nom du type. Sinon, utilisez la syntaxe .class

0
triplestone

Fait intéressant, les différences de performances mentionnées dans l'exemple ci-dessus semblent être liées à d'autres raisons. En utilisant 3 classes différentes, les performances seront en moyenne quasiment les mêmes:

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 sortie sera quelque chose comme:

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

Et changer l'ordre des appels se traduira même par getClass() plus rapide.

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

Sortie:

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