The Difference Between a.getClass() and A.class in Java – Java中a.getClass()和A.class的区别

最后修改: 2020年 9月 27日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In Java, the class java.lang.Class is the entry point of all reflection operations. Once we have an object of java.lang.Class, we can then call the corresponding methods to get the objects of the reflection classes.

在Java中,java.lang.Class是所有反射操作的入口。一旦我们有了java.lang.Class的对象,我们就可以调用相应的方法来获得反射类的对象。

In this tutorial, we’ll discuss the differences between two different ways to get an object of java.lang.Class:

在本教程中,我们将讨论获取java.lang.Class对象的两种不同方式之间的区别。

2. Short Introduction to the Two Approaches

2.两种方法的简短介绍

The Object.getClass() method is an instance method of the Object class. If we have an object, we can call object.getClass() to get the Class object of its type.

Object.getClass()方法是Object类的一个实例方法。如果我们有一个对象,我们可以调用object.getClass()来获得其类型的Class对象。

Similarly, we can use the ClassName.class syntax to get the Class object of the type. An example can explain it clearly:

同样地,我们可以使用ClassName.class语法来获得该类型的Class对象。一个例子可以解释清楚。

@Test
public void givenObjectAndType_whenGettingClassObject_thenTwoMethodsHaveTheSameResult() {
    String str = "I am an object of the String class";

    Class fromStrObject = str.getClass();
    Class clazz = String.class;

    assertSame(fromStrObject, clazz);
}

In the test method above, we try to obtain the Class object of the String class using the two ways we’ve mentioned. Finally, the assertion method tells us that the two Class objects are the same instance.

在上面的测试方法中,我们尝试用我们提到的两种方式获得Class类的String对象。最后,断言方法告诉我们,这两个Class对象是同一个实例。

However, there are differences between the two approaches. Let’s take a closer look at them.

然而,这两种方法之间存在着差异。让我们仔细看看它们。

3. The Runtime Type vs. the Static Type

3.运行时类型与静止类型的比较

Let’s review the previous example quickly. When we call the str.getClass() method, we get the runtime type of the str object. On the other hand, String.class evaluates the String class statically. In this example, the runtime type of str and the String.class are the same.

让我们快速回顾一下之前的例子。当我们调用str.getClass()方法时,我们得到str对象的运行时类型。另一方面,String.class静态地评价String。在这个例子中,strString.class的运行时类型是一样的。

However, they can be different if class inheritance joins the party. Let’s see two simple classes:

然而,如果类的继承加入,它们就会有所不同。让我们看看两个简单的类。

public class Animal {
    protected int numberOfEyes;
}

public class Monkey extends Animal {
    // monkey stuff
}

Now let’s instantiate an object of the Animal class and do another test:

现在让我们实例化一个Animal类的对象并做另一个测试。

@Test
public void givenClassInheritance_whenGettingRuntimeTypeAndStaticType_thenGetDifferentResult() {
    Animal animal = new Monkey();

    Class runtimeType = animal.getClass();
    Class staticType = Animal.class;

    assertSame(staticType, runtimeType);
}

If we run the test above, we’ll get a test failure:

如果我们运行上面的测试,我们会得到一个测试失败。

java.lang.AssertionError: ....
Expected :class com.baeldung.getclassobject.Animal
Actual   :class com.baeldung.getclassobject.Monkey

In the test method, even if we instantiated the animal object by Animal animal = new Monkey(); instead of Monkey animal = new Monkey();, the runtime type of the animal object is still Monkey. This is because the animal object is an instance of Monkey at runtime.

在测试方法中,即使我们通过Animal animal = new Monkey();而不是Monkey animal = new Monkey();来实例化animal对象,animal对象的运行时类型仍然是Monkey。这是因为animal对象在运行时是Monkey的一个实例。

However, when we get the static type of the Animal class, the type is always Animal.

然而,当我们得到Animal类的静态类型时,该类型总是Animal

4. Handling Primitive Types

4.处理原始类型

When we write Java code, we use primitive types quite often. Let’s try to get a Class object of a primitive type using the object.getClass() approach:

当我们写Java代码时,我们经常使用原始类型。让我们试着用object.getClass()的方法来获取一个原始类型的Class对象。

int number = 7;
Class numberClass = number.getClass();

If we try to compile the code above, we’ll get a compilation error:

如果我们试图编译上面的代码,我们会得到一个编译错误。

Error: java: int cannot be dereferenced

The compiler can’t dereference the number variable since it is a primitive variable. Therefore, the object.getClass() method can’t help us to get the Class object of a primitive type.

编译器不能解除对number变量的引用,因为它是一个原始变量。因此,object.getClass()方法不能帮助我们获得原始类型的Class对象。

Let’s see if we can get the primitive type using the .class syntax:

让我们看看是否可以用.class语法得到原始类型。

@Test
public void givenPrimitiveType_whenGettingClassObject_thenOnlyStaticTypeWorks() {
    Class intType = int.class;
    assertNotNull(intType);
    assertEquals("int", intType.getName());
    assertTrue(intType.isPrimitive());
}

So, we can obtain the Class object of the int primitive type through int.class.  In Java version 9 and later, a Class object of primitive type belongs to the java.base module.

因此,我们可以通过int原始类型的Class对象获得int.class。 在Java 9及以后的版本中,原始类型的Class对象属于java.base模块。

As the test shows, the .class syntax is an easy way to get the Class object of a primitive type.

正如测试所示,.class语法是获得原始类型的Class对象的简单方法。

5. Getting the Class Without an Instance

5.获得没有实例的类

We’ve learned that the object.getClass() method can give us the Class object of its runtime type.

我们已经知道,object.getClass()方法可以给我们提供其运行时类型的Class对象。

Now, let’s consider the case where we want to obtain a Class object of a type, but we can’t get an instance of the target type because it’s an abstract class, an interface, or some class doesn’t allow instantiation:

现在,让我们考虑这样的情况:我们想获得一个类型的Class对象,但是我们不能获得目标类型的实例,因为它是一个抽象类,一个接口,或者一些类不允许实例化。

public abstract class SomeAbstractClass {
    // ...
}

interface SomeInterface {
   // some methods ...
}

public class SomeUtils {
    private SomeUtils() {
        throw new RuntimeException("This Util class is not allowed to be instantiated!");
    }
    // some public static methods...
}

In these cases, we can’t get the Class objects of those types using the object.getClass() method, but we can still use the .class syntax to obtain the Class objects of them:

在这些情况下,我们不能使用object.getClass()方法获得这些类型的Class对象,但是我们仍然可以使用.class语法来获得它们的Class对象

@Test
public void givenTypeCannotInstantiate_whenGetTypeStatically_thenGetTypesSuccefully() {
    Class interfaceType = SomeInterface.class;
    Class abstractClassType = SomeAbstractClass.class;
    Class utilClassType = SomeUtils.class;

    assertNotNull(interfaceType);
    assertTrue(interfaceType.isInterface());
    assertEquals("SomeInterface", interfaceType.getSimpleName());

    assertNotNull(abstractClassType);
    assertEquals("SomeAbstractClass", abstractClassType.getSimpleName());

    assertNotNull(utilClassType);
    assertEquals("SomeUtils", utilClassType.getSimpleName());
}

As the test above shows, the .class syntax can obtain the Class objects for those types.

正如上面的测试所示,.class语法可以获得这些类型的Class对象。

Therefore, when we want to have the Class object, but we cannot get an instance of the type, the .class syntax is the way to go.

因此,当我们想拥有Class对象,但我们无法获得该类型的实例时,.class语法是我们的选择。

6. Conclusion

6.结语

In this article, we learned two different ways to get the Class object of a type: the object.getClass() method and the .class syntax.

在这篇文章中,我们学习了两种不同的方法来获取一个类型的Class对象:object.getClass()方法和.class语法。

Later, we discussed the difference between the two approaches. The following table can give us a clear overview:

后来,我们讨论了这两种方法之间的区别。下表可以给我们一个清晰的概述。

object.getClass() SomeClass.class
Class objects The runtime type of object The static Type of SomeClass
Primitive types Works straightforwardly
Interfaces, abstract classes, or classes that can’t be instantiated Works straightforwardly

 

As always, the full source code of the article is available over on GitHub.

一如既往,该文章的完整源代码可在GitHub上获得