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()
.
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 A
statiquement, 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 .
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.
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
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
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
}
}
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
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