JAVA類的頂層Type抽象和繼承關係
type的繼承關係
- Type是java對於型別的高階抽象,是所有型別的父親
Type的子型別 | 用途 | 舉例 |
---|---|---|
引數化型別(ParameterizedType) | 用來描述泛型,泛型定義只能在class、construct、method上 | List<T>、Map<K,V>等帶有引數化的物件 |
泛型陣列(GenericArrayType) | 描述泛型陣列 | List<String>[] 、T[]等;注意Integer[],int[] 等不屬於GenericArrayType,而屬於普通型別(Class,isArray()方法返回true) |
型別變數(TypeVariable) | 描述<>裡面內容,描述泛型的具體型別 | Class<T>中的T |
萬用字元變數(WidecardType) | 描述<>裡面內容,描述泛型的萬用字元 | Class<?>中的? |
原始型別(Class) | java物件的class,包括類、美劇、陣列、註解 | Integer.class、Object.class |
基本型別(Class) | java的8種基本型別的class | 基本型別的class,如 int.class |
ParameterizedType
介面說明
public interface ParameterizedType extends Type {}
方法 | 用途 | 舉例 |
---|---|---|
Type[] getActualTypeArguments(); | 獲取泛型<T,U>的內容,若無泛型則返回空陣列 | 對於Map<String,Integer>返回的Type[]為String和Integer |
Type getRawType(); | 獲取<>前面的類 | 對於Map<String,Integer>返回的Type為Map |
Type getOwnerType(); | 獲取<>前面的類(記為A)的擁有者,如果A是頂層類,那麼此方法返回null | if this type is {@code O<T>.I<S>}, return a representation of {@code O<T>} |
用法
public class ParameterizedTypeTest {
public static class GenericType<T,U> {
}
public static interface GenericResult<R> {
}
public static class Instance<T,U,R> extends GenericType<T,U> implements GenericResult<R> {
}
public static void main(String[] args) {
Instance<String, Double, Integer> instance = new Instance<>();
// 型別是ParameterizedType:只有一個元素GenericResult<R>
Type[] types = instance.getClass().getGenericInterfaces();
// 型別是ParameterizedType:表示GenericType<T, U>
Type type = instance.getClass().getGenericSuperclass();
ParameterizedType parameterizedType = (ParameterizedType) type;
// 型別是TypeVariable:兩個元素T, U
Type[] actualTypes = parameterizedType.getActualTypeArguments();
// 型別是class : 不論GenericType是內部類,還是靜態內部類,其父類都是Test.class
Type ownerType = parameterizedType.getOwnerType();
// 型別是class : GenericType
Type rawType = parameterizedType.getRawType();
// GenericType.toString() : Test$GenericType<T, U>
String typeName = parameterizedType.getTypeName();
// 型別是class : class sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
Class<? extends ParameterizedType> clazz = parameterizedType.getClass();
}
}
GenericArrayType
介面說明
public interface GenericArrayType extends Type {}
方法 | 用途 | 舉例 |
---|---|---|
Type getGenericComponentType(); | 獲取陣列的門面型別 | List<?>[]得到的是List<?> |
用法
@FieldNameConstants
public class GenericArrayTypeTest<T> {
private List<String>[] stringListArray;
private List<?>[] noBoundListArray;
private T[] tArray;
private int[] intArray;
public static void main(String[] args) {
handle(GenericArrayTypeTest.FIELD_STRING_LIST_ARRAY);
handle(GenericArrayTypeTest.FIELD_NO_BOUND_LIST_ARRAY);
handle(GenericArrayTypeTest.FIELD_T_ARRAY);
handle(GenericArrayTypeTest.FIELD_INT_ARRAY);
}
@SneakyThrows
private static void handle(String fieldName) {
Field field = GenericArrayTypeTest.class.getDeclaredField(fieldName);
/**
* <ul>
* <li>stringListArray : 型別GenericArrayType : List<String>[]是泛型陣列</li>
* <li>noBoundListArray : 型別GenericArrayType : List<?>[]是泛型陣列</li>
* <li>tArray : 型別GenericArrayType : T[]是泛型陣列</li>
* <li>intArray : 不是泛型陣列, 解析報錯</li>
* </ul>
*/
Type genericType = field.getGenericType();
GenericArrayType genericArrayType = (GenericArrayType) genericType;
/**
* <ul>
* <li>stringListArray : 型別是ParameterizedType : List<String></li>
* <li>noBoundListArray : 型別是ParameterizedType : List<?></li>
* <li>tArray : 型別是型別TypeVariable : T</li>
* <li>intArray : 不是泛型陣列, 解析報錯</li>
* </ul>
*/
Type genericComponentType = genericArrayType.getGenericComponentType();
System.out.println(genericComponentType); // java.util.List<java.lang.String>
}
}
TypeVariable
介面說明
public interface TypeVariable extends Type, AnnotatedElement {}
方法 | 用途 | 舉例 |
---|---|---|
Type[] getBounds(); | 獲取泛型的上界,無顯示定義extends定義上界,則預設上界為Object | |
D getGenericDeclaration(); | Java中可以宣告泛型變數的地方有三個class,contructor和method。此方法就是獲取到宣告型別變數的語法元素(指向哪個class,哪個class的哪個構造方法,哪個class的哪個方法) | |
String getName(); | 獲取名稱,即K,V | |
AnnotatedType[] getAnnotatedBounds(); |
用法
// 型別TypeVariable : 返回A,B
TypeVariable<Class<GenericType>>[] typeVariables = GenericType.class.getTypeParameters();
// 型別Class : Serializable
Type[] aBoundType = typeVariables[0].getBounds();
// 型別Class : Object
Type[] bBoundType = typeVariables[1].getBounds();
// 型別String : A
String aName = typeVariables[0].getTypeName();
// 型別String : B
String bName = typeVariables[1].getTypeName();
// 型別Class : 定義泛型A,B的類TypeVariableTest$GenericType
typeVariables[0].getGenericDeclaration();
// 型別Class : 定義泛型A,B的類TypeVariableTest$GenericType
typeVariables[1].getGenericDeclaration();
WildcardType
介面說明
public interface TypeVariable extends Type, AnnotatedElement {}
方法 | 用途 | 舉例 |
---|---|---|
Type[] getUpperBounds(); | 獲取?的上界,預設上界為Object | |
Type[] getLowerBounds(); | 獲取?的下界。若無下界則返回空陣列 |
用法
public static class GenericType {
public String print(List<? extends String> aList, List<? super Integer> bList) throws Exception {
return aList.toString();
}
@SneakyThrows
public static void main(String[] args) {
// 獲取 String print(List<? extends String> aList, List<? super Integer> bList) throws Exception
Method method = GenericType.class.getDeclaredMethod("print", List.class, List.class);
// 獲取形參 List<? extends String> aList, List<? super Integer> bList
Type[] genericParameterTypes = method.getGenericParameterTypes();
// 獲取泛型萬用字元 ? extends String
Type aListWildcard = ((ParameterizedType) genericParameterTypes[0]).getActualTypeArguments()[0];
WildcardType aListWildcardType = (WildcardType) aListWildcard;
// 列印[class java.lang.String]
System.out.println(Arrays.toString(aListWildcardType.getUpperBounds()));
// 列印[]
System.out.println(Arrays.toString(aListWildcardType.getLowerBounds()));
// 獲取泛型萬用字元? super Integer
Type bListWildcard = ((ParameterizedType) genericParameterTypes[1]).getActualTypeArguments()[0];
WildcardType bListWildcardType = (WildcardType) bListWildcard;
// 列印[class java.lang.Object]
System.out.println(Arrays.toString(bListWildcardType.getUpperBounds()));
// 列印[class java.lang.Integer]
System.out.println(Arrays.toString(bListWildcardType.getLowerBounds()));
}
}
Class
方法說明
類和物件的關係判斷
- instanceof
- 用法 Object instanceof Class
- instanceof是Java中的二元運算子,左邊是物件,右邊是類;當物件是右邊類或子類所建立物件時,返回true;否則,返回false
- 左邊不能是基礎型別
- null用instanceof跟任何型別比較時都是false
- Class.isInstanceof(Object)
- 與instanceof功能等價
- Class.isAssignableFrom(Class)
- 類和類的關係判斷,如果左側是右側的父類或本類,則返回true
public static class Father { }
public static class Son extends Father { }
public static void main(String[] args) {
Father father = new Father();
Son son = new Son();
System.out.println(father instanceof Father);// true
System.out.println(son instanceof Father);// true
System.out.println(Father.class.isInstance(father));// true
System.out.println(Father.class.isInstance(son));// true
System.out.println(Father.class.isAssignableFrom(Father.class));// true
System.out.println(Father.class.isAssignableFrom(Son.class));// true
System.out.println(Son.class.isAssignableFrom(Father.class));// false
}
獲取名稱
- getName()
獲取全路徑類名
public String getName() {
String name = this.name;
if (name == null)
this.name = name = getName0();
return name;
}
private native String getName0();
如果是基本型別,則返回byte、void等
如果是物件型別,則返回全路徑(包名+類名)
如果是陣列型別,則按照下面的格式返回
2. getTypeName()
和getName()區別在於陣列型別,對陣列型別的展示方法進行優化,轉換符合java語法的形式
public String getTypeName() {
if (isArray()) {
try {
Class<?> cl = this;
int dimensions = 0;
while (cl.isArray()) {
dimensions++;
cl = cl.getComponentType();
}
StringBuilder sb = new StringBuilder();
sb.append(cl.getName());
for (in t i = 0; i < dimensions; i++) {
sb.append("[]");
}
return sb.toString();
} catch (Throwable e) { /*FALLTHRU*/ }
}
return getName();
}
System.out.println((new Object[3]).getClass().getName());//[Ljava.lang.Object;
System.out.println((new Object[3]).getClass().getTypeName());//java.lang.Object[]
System.out.println((new int[3][4][5][6][7][8][9]).getClass().getName());//[[[[[[[I
System.out.println((new int[3][4][5][6][7][8][9]).getClass().getTypeName());//int[][][][][][][]
- getCanonicalName()
- 和getTypeName()區別在於內部類,對於普通內部類,返回符合java語言書寫規範的全路徑。
對於匿名內部類則返回null
public class ClassTest {
public static class Father { }
public static class Son extends Father { }
public static void main(String[] args) {
// 普通類
Father father = new Father();
System.out.println("----普通類----");
System.out.println(father.getClass().getName());//ClassTest$Father
System.out.println(father.getClass().getTypeName());//ClassTest$Father
System.out.println(father.getClass().getCanonicalName());//ClassTest.Father
System.out.println(father.getClass().getSimpleName());
}
}
- getSimpleName()
- 獲取簡單類名,在getCanonicalName()的基礎上,去掉package路徑
對於不同型別,以上方法的返回值
public class ClassTest {
public static class Father { }
public static void main(String[] args) {
// 普通類
Father father = new Father();
System.out.println("----普通類----");
System.out.println(father.getClass().getName());//ClassTest$Father
System.out.println(father.getClass().getTypeName());//ClassTest$Father
System.out.println(father.getClass().getCanonicalName());//ClassTest.Father
System.out.println(father.getClass().getSimpleName());//Father
// 匿名類
Father inner = new Father(){};
System.out.println("----內部類----");
System.out.println(inner.getClass().getName());//ClassTest$1
System.out.println(inner.getClass().getTypeName());//ClassTest$1
System.out.println(inner.getClass().getCanonicalName());//null
System.out.println(inner.getClass().getSimpleName());//空字串
// 陣列
Father[] array = new Father[1];
System.out.println("----物件陣列類----");
System.out.println(array.getClass().getName());//[LClassTest$Father;
System.out.println(array.getClass().getTypeName());//ClassTest$Father[]
System.out.println(array.getClass().getCanonicalName());//ClassTest.Father[]
System.out.println(array.getClass().getSimpleName());//Father[]
// 基本型別陣列
int[] rawArray = new int[1];
System.out.println("----基本型別陣列類----");
System.out.println(rawArray.getClass().getName());//[I
System.out.println(rawArray.getClass().getTypeName());//int[]
System.out.println(rawArray.getClass().getCanonicalName());//int[]
System.out.println(rawArray.getClass().getSimpleName());//int[]
}
}
- class.getDeclaringClass()和field.getDeclaringClass()方法的用途
@FieldNameConstants
public class ClassTest {
private Father father;
public ClassTest() {
this.father = new Father();
}
public static class Father {
}
@SneakyThrows
public static void main(String[] args) {
ClassTest classTest = new ClassTest();
// class ClassTest
System.out.println(classTest.father.getClass().getDeclaringClass());
// class ClassTest
Field field = ClassTest.class.getDeclaredField(ClassTest.FIELD_FATHER);
System.out.println(field.getDeclaringClass());
}
}
參考
相關文章
- Java之繼承和抽象類Java繼承抽象
- JAVA介面繼承、抽象類等Java繼承抽象
- PHP 抽象類繼承抽象類時的注意點PHP 抽象類繼承抽象類時的注意點PHP抽象繼承
- 繼承 重寫和抽象類繼承抽象
- PHP中類的繼承關係PHP繼承
- Qt類繼承關係圖QT繼承
- PHP 抽象類繼承抽象類時的注意點PHP抽象繼承
- 關於Java中的物件、類、抽象類、介面、繼承之間的聯絡Java物件抽象繼承
- 繼承+多型+抽象類繼承多型抽象
- C# OOP:繼承,介面和抽象類C#OOP繼承抽象
- Java抽象類、繼承及多型和介面卡的實現Java抽象繼承多型
- 【Java】繼承、抽象、組合Java繼承抽象
- java抽象繼承-模板方法Java抽象繼承
- Java基礎10 介面的繼承與抽象類Java繼承抽象
- 繼承關係和魔術方法繼承
- c# abstract抽象類及抽象方法_繼承C#抽象繼承
- C++ exception 異常類繼承關係C++Exception繼承
- 【JAVA】筆記(5)--- final;抽象方法;抽象類;介面;解析繼承,關聯,與實現;Java筆記抽象繼承
- Java面試題:Java中的集合及其繼承關係Java面試題繼承
- ArrayList繼承關係分析繼承
- 6-2 抽象類的繼承 (5分)抽象繼承
- java繼承關係下執行順序Java繼承
- Java的類與繼承Java繼承
- c++中的繼承關係C++繼承
- Java:類與繼承Java繼承
- JS原型繼承和類式繼承JS原型繼承
- 類的繼承_子類繼承父類繼承
- 類的繼承和派生繼承
- 介面是否可繼承(extends)介面? 抽象類是否可實現 (implements)介面? 抽象類是否可繼承具體類(concrete class)?繼承抽象
- angular中$scope作用域和繼承關係解析Angular繼承
- 介面、抽象類、普通類之間的關係抽象
- JAVA學習線路:day01物件導向(繼承、抽象類)Java物件繼承抽象
- 5. JPA物件繼承關係物件繼承
- C++標準庫中檔案流類的繼承關係C++繼承
- #JAVA#物件導向(繼承中成員方法的關係)Java物件繼承
- C#介面、抽象類、普通類和繼承(子類與父類)都有其特定的用途和場景C#抽象繼承
- Java集合為什麼設計為:實現類繼承了抽象類,同時實現抽象類實現的介面Java繼承抽象
- 征服 JavaScript 面試:類繼承和原型繼承的區別JavaScript面試繼承原型