Java中a.getClass方法和A.class之間的區別
- java
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 的靜態類型 |
原始類型 | - | 直接工作 |
接口,抽像類或無法實例化的類 | - | 直接工作 |