简体   繁体   English

Java 中的 a.getClass() 和 A.class 有什么区别?

[英]What is the difference between a.getClass() and A.class in Java?

In Java what pros/cons exist surrounding the choice to use a.getClass() or A.class ?在 Java 中,围绕使用a.getClass()A.class的选择存在哪些优点/缺点? Either can be used wherever a Class<?> is expected, but I imagine that there would be performance or other subtle benefits to using both in different circumstances (just like there are with Class.forName() and ClassLoader.loadClass() .两者都可以在需要Class<?>任何地方使用,但我想在不同的情况下使用两者会有性能或其他微妙的好处(就像Class.forName()ClassLoader.loadClass()

I wouldn't compare them in terms of pros/cons since they have different purposes and there's seldom a "choice" to make between the two.我不会在利弊方面比较它们,因为它们有不同的目的,而且两者之间很少有“选择”。

  • a.getClass() returns the runtime type of a . a.getClass()返回的运行时类型a Ie, if you have A a = new B();即,如果你有A a = new B(); then a.getClass() will return the B class.然后a.getClass()将返回B类。

  • A.class evaluates to the A class statically , and is used for other purposes often related to reflection. A.class静态评估为A类,并用于其他经常与反射相关的目的。

In terms of performance, there may be a measurable difference, but I won't say anything about it because in the end it is JVM and/or compiler dependent.在性能方面,可能存在可测量的差异,但我不会对此进行任何说明,因为最终它取决于 JVM 和/或编译器。


This post has been rewritten as an article here .这篇文章在这里被改写为一篇文章。

They are actually different with regards to where you can use them.它们实际上在您可以使用它们的地方方面有所不同。 A.class works at compile time while a.getClass() requires an instance of type A and works at runtime. A.class在编译时工作,而a.getClass()需要类型A的实例并在运行时工作。

There may be a performance difference as well.也可能存在性能差异。 While A.class can be resolved by the compiler because it knows the actual type of A , a.getClass() is a virtual method call happening at runtime.虽然A.class可以由编译器解析,因为它知道A的实际类型,但a.getClass()是在运行时发生的虚拟方法调用。

For reference, a compiler targeting bytecode typically emits the following instructions for Integer.getClass() :作为参考,以字节码为目标的编译器通常会为Integer.getClass()发出以下指令:

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

and the following for Integer.class :以及Integer.class的以下内容:

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

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

The former would typically involve a virtual method dispatch and therefore presumably take longer time to execute.前者通常涉及虚拟方法分派,因此可能需要更长的时间来执行。 That is in the end JVM-dependent however.然而,这最终取决于 JVM。

have a look at the examples below看看下面的例子

a.getClass()!= A.class , ie a is not an instance of A but of an anonymous sub class of A a.getClass()!= A.class ,即 a 不是 A 的实例,而是 A 的匿名子类

a.getClass() requires an instance of type A a.getClass()需要一个类型为 A 的实例

Use a.getClass when you have an instance of class/type and you want to get exact type of it.当您有一个类/类型的实例并且想要获得它的确切类型时,请使用a.getClass while a.class is used when you have type available and you want to create instance of it.a.class当您有可用的type并且想要创建它的实例时使用。
Also getClass() returns runtime type of instance while .class is evaluated at compile time. getClass()返回实例的运行时类型,而.class在编译时进行评估。
Considering performance of getClass() and .class , .class has better performance than getClass() .考虑到getClass().class性能, .classgetClass()有更好的性能。
Example :例子 :

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

}

Output :输出 :

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

There is one difference i would like to add.我想补充一个区别。 Let us say you have a class a constructor as shown below with a super class which takes a Class object.假设您有一个构造函数类,如下所示,其中有一个带有 Class 对象的超类。 You want that whenever a subclass object is created the subClass' class object should be passed to the super class.您希望无论何时创建子类对象,都应将子类的类对象传递给超类。 Below code will not compile as you cannot call an instance method in a constructor.下面的代码将无法编译,因为您无法在构造函数中调用实例方法。 In that case if you replace myObject.getClass() with MyClass.class .在这种情况下,如果您将myObject.getClass()替换为MyClass.class It will run perfectly.它将完美运行。

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

Interestingly the differences in performance mentioned in the example above, seem to be related to other reasons.有趣的是,上面示例中提到的性能差异似乎与其他原因有关。 Using 3 different Classes, in average the performance will be nearly the same :使用 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");
} }

The Output will be something like :输出将类似于:

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

And switching the order of the calls will even result in getClass() being faster.切换调用顺序甚至会导致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");
}}

Output:输出:

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

p.getClass() , where the p is an instance of an object, returns the runtime class of this object p . p.getClass() ,其中p是一个对象的实例,返回这个对象p的运行时类。 p cannot be a type which will cause a compile-time error, it should be an instance of an object. p不能是会导致编译时错误的类型,它应该是对象的实例。

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

p.class is an expression. p.class是一个表达式。 The .class is called the class syntax. .class称为类语法。 p is a type. p是一种类型。 It can be the name of a class, interface or array and even a primitive type.它可以是类、接口或数组的名称,甚至是原始类型。 a.getClass() == B.class . a.getClass() == B.class

If a type is available and there is an instance then it is possible to use getClass method to get the name of the type.如果一个类型可用并且有一个实例,那么可以使用getClass方法来获取类型的名称。 Otherwise, use the .class syntax否则,使用.class语法

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM