В Java какие плюсы/минусы существуют вокруг выбора использовать a.getClass()
или A.class
? Любой из них может использоваться везде, где ожидается Class<?>
, но я полагаю, что производительность и другие тонкие преимущества могут быть использованы как в разных обстоятельствах (как и при использовании Class.forName()
и ClassLoader.loadClass()
.
В чем разница между a.getClass() и A.class в Java?
Ответ 1
Я бы не стал сравнивать их с точки зрения плюсов и минусов, поскольку они имеют разные цели, и редко бывает "выбор" между ними.
-
a.getClass()
возвращает тип выполненияa
. I.e., если у вас естьA a = new B();
, тоa.getClass()
вернет классB
. -
A.class
оценивает классa
статически и используется для других целей, часто связанных с отражением.
В плане производительности может быть измеримая разница, но я ничего не буду говорить об этом, потому что в конце это JVM и/или компилятор.
Это сообщение было переписано как статья здесь.
Ответ 2
Они на самом деле различны в отношении того, где вы можете их использовать. A.class
работает во время компиляции, а a.getClass()
требует экземпляра типа A
и работает во время выполнения.
Также может быть разница в производительности. Хотя A.class
может быть разрешен компилятором, поскольку он знает фактический тип A
, a.getClass()
- это вызов виртуального метода во время выполнения.
Для справки, байт-код для таргетинга компилятора обычно генерирует следующие инструкции для 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.
Ответ 3
рассмотрим приведенные ниже примеры
a.getClass()!= A.class
, то есть a не является экземпляром A, а анонимного подкласса
A
a.getClass()
требуется экземпляр типа A
Ответ 4
Используйте a.getClass
, если у вас есть экземпляр класса/типа, и вы хотите получить его точный тип. а a.class
используется, если у вас есть type
, и вы хотите создать его экземпляр.
Кроме того, 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
Ответ 5
Есть одна разница, которую я хотел бы добавить. Скажем, у вас есть класс конструктор, как показано ниже, с суперклассом, который принимает объект класса. Вы хотите, чтобы всякий раз, когда был создан объект подкласса, объект класса subClass должен быть передан суперклассу. Ниже код не будет компилироваться, поскольку вы не можете вызвать метод экземпляра в конструкторе. В этом случае, если вы замените myObject.getClass()
на MyClass.class
. Он будет работать отлично.
Class MyClass
{
private MyClass myObject = new MyClass();
public MyClass()
{
super(myObject.getClass()); //error line compile time error
}
}
Ответ 6
Интересно, что различия в производительности, упомянутые в приведенном выше примере, по-видимому, связаны с другими причинами. Используя 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");
} }
Результат будет примерно таким:
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