Spring 泛型處理
Java 泛型基礎
• 泛型型別
- 泛型型別是在型別上引數化的泛型類或介面
• 泛型使用場景
- 編譯時強型別檢查
- 避免型別強轉
- 實現通用演算法
Java 泛型基礎
泛型型別擦寫
泛型被引入到 Java 語言中,以便在編譯時提供更嚴格的型別檢查並支援泛型程式設計。型別擦除確保不會為引數化型別建立新類;因此,泛型不會產生執行時開銷。為了實現泛型,編譯器將型別擦除應用於:
• 將泛型型別中的所有型別引數替換為其邊界,如果型別引數是無邊界的,則將其替換為
“Object”。因此,生成的位元組碼只包含普通類、介面和方法。
• 必要時插入型別轉換以保持型別安全。
• 生成橋方法以保留擴充套件泛型型別中的多型性。
public class GenericDemo {
public static void main(String[] args) {
// Java 7 Diamond 語法
Collection<String> list = new ArrayList<>();
list.add("Hello");
list.add("World");
// 編譯時錯誤
// list.add(1);
// 泛型擦寫
Collection temp = list;
// 編譯通過
temp.add(1);
System.out.println(list);
}
}
Java 5 型別介面
• Java 5 型別介面 - java.lang.reflect.Type
派生類或介面 | 說明 |
---|---|
java.lang.Class | Java 類 API,如 java.lang.String |
java.lang.reflect.GenericArrayType | 泛型陣列型別 |
java.lang.reflect.ParameterizedType | 泛型引數型別 |
java.lang.reflect.TypeVariable | 泛型型別變數,如 Collection 中的 E |
java.lang.reflect.WildcardType | 泛型通配型別 |
• Java 泛型反射 API
型別 | API |
---|---|
泛型資訊(Generics Info) | java.lang.Class#getGenericInfo() |
泛型引數(Parameters) | java.lang.reflect.ParameterizedType |
泛型父類(Super Classes) | java.lang.Class#getGenericSuperclass() |
泛型介面(Interfaces) | java.lang.Class#getGenericInterfaces() |
泛型宣告(Generics Declaration) | java.lang.reflect.GenericDeclaration |
Spring 泛型型別輔助類
核心 API - org.springframework.core.GenericTypeResolver
• 版本支援:[2.5.2 , )
• 處理型別相關(Type)相關方法
- resolveReturnType
- resolveType
• 處理泛型引數型別(ParameterizedType)相關方法
- resolveReturnTypeArgument
- resolveTypeArgument
- resolveTypeArguments
• 處理泛型型別變數(TypeVariable)相關方法
- getTypeVariableMap
class StringList extends ArrayList<String> { // 泛型引數具體化(位元組碼有記錄)
}
/**
* {@link GenericTypeResolver} 示例
*/
public class GenericTypeResolverDemo {
public static void main(String[] args) throws NoSuchMethodException {
// String 是 Comparable<String> 具體化
displayReturnTypeGenericInfo(GenericTypeResolverDemo.class, Comparable.class, "getString");
// ArrayList<Object> 是 List 泛型引數型別的具體化
displayReturnTypeGenericInfo(GenericTypeResolverDemo.class, List.class, "getList");
// StringList 也是 List 泛型引數型別的具體化
displayReturnTypeGenericInfo(GenericTypeResolverDemo.class, List.class, "getStringList");
// 具備 ParameterizedType 返回,否則 null
// TypeVariable
Map<TypeVariable, Type> typeVariableMap = GenericTypeResolver.getTypeVariableMap(StringList.class);
System.out.println(typeVariableMap);
}
public static StringList getStringList() {
return null;
}
public static ArrayList<Object> getList() { // 泛型引數型別具體化
return null;
}
public static String getString() {
return null;
}
private static void displayReturnTypeGenericInfo(Class<?> containingClass, Class<?> genericIfc, String methodName, Class... argumentTypes) throws NoSuchMethodException {
Method method = containingClass.getMethod(methodName, argumentTypes);
// 宣告類 GenericTypeResolverDemo.class
Class<?> returnType = resolveReturnType(method, containingClass);
// 常規類作為方法返回值
System.out.printf("GenericTypeResolver.resolveReturnType(%s,%s) = %s\n", methodName, containingClass.getSimpleName(), returnType);
// 常規型別不具備泛型引數型別 List<E>
Class<?> returnTypeArgument = resolveReturnTypeArgument(method, genericIfc);
System.out.printf("GenericTypeResolver.resolveReturnTypeArgument(%s,%s) = %s\n", methodName, containingClass.getSimpleName(), returnTypeArgument);
}
}
Spring 泛型集合型別輔助類
核心 API - org.springframework.core.GenericCollectionTypeResolver
• 版本支援:[2.0 , 4.3]
• 替換實現:org.springframework.core.ResolvableType
• 處理 Collection 相關
- getCollection*Type
• 處理 Map 相關
- getMapKey*Type
- getMapValue*Type
/**
* {@link GenericCollectionTypeResolver} 示例
*/
public class GenericCollectionTypeResolverDemo {
private static StringList stringList;
private static List<String> strings;
public static void main(String[] args) throws Exception {
// StringList extends ArrayList<String> 具體化
// getCollectionType 返回具體化泛型引數型別集合的成員型別 = String
System.out.println(GenericCollectionTypeResolver.getCollectionType(StringList.class));
System.out.println(GenericCollectionTypeResolver.getCollectionType(ArrayList.class));
// 獲取欄位
Field field = GenericCollectionTypeResolverDemo.class.getDeclaredField("stringList");
System.out.println(GenericCollectionTypeResolver.getCollectionFieldType(field));
field = GenericCollectionTypeResolverDemo.class.getDeclaredField("strings");
System.out.println(GenericCollectionTypeResolver.getCollectionFieldType(field));
}
}
Spring 方法引數封裝
核心 API - org.springframework.core.MethodParameter
• 起始版本:[2.0 , )
• 元資訊
- 關聯的方法 - Method
- 關聯的構造器 - Constructor
- 構造器或方法引數索引 - parameterIndex
- 構造器或方法引數型別 - parameterType
- 構造器或方法引數泛型型別 - genericParameterType
- 構造器或方法引數引數名稱 - parameterName
- 所在的類 - containingClass
Spring 4.0 泛型優化實現 - ResolvableType
核心 API - org.springframework.core.ResolvableType
• 起始版本:[4.0 , )
• 扮演角色:GenericTypeResolver 和 GenericCollectionTypeResolver 替代者
• 工廠方法:for* 方法
• 轉換方法:as* 方法
• 處理方法:resolve* 方法
/**
* {@link ResolvableType} Demo
*/
public class ResolvableTypeDemo {
public static void main(String[] args) {
// 工廠建立
// StringList <- ArrayList <- AbstractList <- List <- Collection
ResolvableType resolvableType = ResolvableType.forClass(StringList.class);
resolvableType.getSuperType(); // ArrayList
resolvableType.getSuperType().getSuperType(); // AbstractList
System.out.println(resolvableType.asCollection().resolve()); // 獲取 Raw Type
System.out.println(resolvableType.asCollection().resolveGeneric(0)); // 獲取泛型引數型別
}
}
ResolvableType 的侷限性
• 侷限一:ResolvableType 無法處理泛型擦寫
• 侷限二:ResolvableType 無法處理非具體化的 ParameterizedType
面試題
Java 泛型擦寫發生在編譯時還是執行時?
答:執行時
請介紹 Java 5 Type 型別的派生類或介面?
答:
• java.lang.Class
• java.lang.reflect.GenericArrayType
• java.lang.reflect.ParameterizedType
• java.lang.reflect.TypeVariable
• java.lang.reflect.WildcardType
請說明 ResolvableType 的設計優勢?
答:
• 簡化 Java 5 Type API 開發,遮蔽複雜 API 的運用,如 ParameterizedType
• 不變性設計(Immutability)
• Fluent API 設計(Builder 模式),鏈式(流式)程式設計
相關文章
- spring泛型注入Spring泛型
- Swift---協議和擴充套件、 錯誤處理、泛型Swift協議套件泛型
- 泛型類、泛型方法及泛型應用泛型
- 【java】【泛型】泛型geneticJava泛型
- 【Spring】Spring後置處理器Spring
- 泛型類和泛型方法泛型
- 泛型--泛型萬用字元和泛型的上下限泛型字元
- TypeScript 泛型介面和泛型類TypeScript泛型
- Go 泛型之泛型約束Go泛型
- Unity Shader-後處理:Bloom全屏泛光UnityOOM
- 泛型泛型
- Spring 中優雅的獲取泛型資訊Spring泛型
- Spring Boot 異常處理Spring Boot
- Spring處理@Configuration的分析Spring
- Spring系列(七) Spring MVC 異常處理SpringMVC
- 泛型最佳實踐:Go泛型設計者教你如何用泛型泛型Go
- TypeScript 泛型型別TypeScript泛型型別
- 型別 VS 泛型型別泛型
- Spring Boot 之 Spring Batch 批處理實踐Spring BootBAT
- Spring之後置處理器Spring
- 泛型類、泛型方法、型別萬用字元的使用泛型型別字元
- 泛型(一)泛型
- 泛型(三)泛型
- 泛型(二)泛型
- 泛型(四)泛型
- 泛型(五)泛型
- Java泛型Java泛型
- 泛型viewmodle泛型View
- 泛型(Generic)泛型
- Go 泛型Go泛型
- 29.Spring Boot中異常處理與REST格式處理Spring BootREST
- 【譯】在非泛型類中建立泛型方法泛型
- 《Spring Batch 權威指南》之“批處理和 Spring”SpringBAT
- 泛型型別(.NET 指南)泛型型別
- Java函式泛型List引數,操作泛型元素Java函式泛型
- Go 官方出品泛型教程:如何開始使用泛型Go泛型
- Spring是如何處理註解的Spring
- spring boot 統一異常處理Spring Boot