1.概述
在Java中,类java.lang.Class
是所有反射操作的入口点。一旦有了java.lang.Class
对象,就可以调用相应的方法来获取反射类的对象。
在本教程中,我们将讨论两种不同的获取java.lang.Class
对象的方式之间的区别:
- 调用
Object.getClass()
方法 - 使用
.class
语法
2.两种方法的简要介绍
Object.getClass()
Object
类的实例方法。如果有一个对象,则可以调用object.getClass()
以获取其类型Class
同样,我们可以使用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);
}
在上面的测试方法中,我们尝试使用我们提到的两种方法String
Class
对象。最后,断言方法告诉我们两个Class
象是同一实例。
但是,这两种方法之间存在差异。让我们仔细看看它们。
3.运行时类型与静态类型
让我们快速回顾一下前面的示例。**当我们调用str.getClass()
方法时,我们将获得str
对象的运行时类型。另一方面, String.class
静态评估String
**类。在此示例中, str
和String.class
的运行时类型相同。
但是,如果使用了类继承,则它们可以不同。让我们看两个简单的类:
public class Animal {
protected int numberOfEyes;
}
public class Monkey extends Animal {
// monkey stuff
}
现在,让我们实例化Animal
类的对象并进行另一个测试:
@Test
public void givenClassInheritance_whenGettingRuntimeTypeAndStaticType_thenGetDifferentResult() {
Animal animal = new Monkey();
Class runtimeType = animal.getClass();
Class staticType = Animal.class;
assertSame(staticType, runtimeType);
}
如果我们运行上面的测试,将会导致测试失败:
java.lang.AssertionError: ....
Expected :class com.baeldung.getclassobject.Animal
Actual :class com.baeldung.getclassobject.Monkey
在测试方法中,即使我们通过Animal animal = new Monkey();
animal
而不是Monkey animal = new Monkey();
animal
对象的运行时类型仍然是Monkey.
这是因为animal
像在运行时Monkey
的实例。
但是,当我们获得Animal
类的静态类型时,该类型始终是Animal
。
4.处理基本类型
在编写Java代码时,我们经常使用基本类型。让我们尝试object.getClass()
方法获取原始类型Class
int number = 7;
Class numberClass = number.getClass();
如果我们尝试编译上面的代码,则会收到编译错误:
Error: java: int cannot be dereferenced
编译器不能取消引用number
变量,因为它是原始变量。因此, object.getClass()
方法无法帮助我们获取基本类型Class
让我们看看是否可以使用.class
语法获取原始类型:
@Test
public void givenPrimitiveType_whenGettingClassObject_thenOnlyStaticTypeWorks() {
Class intType = int.class;
assertNotNull(intType);
assertEquals("int", intType.getName());
assertTrue(intType.isPrimitive());
}
因此,我们可以int.class
int
基本类型Class
对象。在Java版本9和更高版本中,原始类型Class
java.base
模块。
如测试所示, .class
语法是获取原始类型Class
5.在没有实例的情况下获取类
我们已经了解到object.getClass()
方法可以为我们提供其运行时类型Class
现在,让我们考虑要获取Class
对象但由于目标类是abstract
类, interface,
或某些类不允许实例化而无法获取目标类型的实例的情况:
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...
}
在这些情况下,我们无法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());
}
如上面的测试所示, .class
语法可以获取这些类型Class
因此,当我们想拥有Class
对象,但又无法获得该类型的实例时, .class
语法是可行的方法。
六,结论
在本文中,我们学习了两种获取Class
对象的object.getClass()
方法和.class
语法。
稍后,我们讨论了两种方法之间的区别。下表可以给我们清晰的概述:
object.getClass() | SomeClass.class | |
---|---|---|
类对象 | object 的运行时类型 | SomeClass 的静态类型 |
原始类型 | - | 直接工作 |
接口,抽像类或无法实例化的类 | - | 直接工作 |
0 评论