Java泛型体系知识学习

举报
西魏陶渊明 发表于 2022/09/25 01:38:38 2022/09/25
【摘要】 真正的猛士,每天干一碗毒鸡汤! 问世间钱为何物,只叫人生死相许。!😄 # 一、Java泛型体系 Type 是 Java 语言中所有类型的公共父接口,其从 JDK5 开始引入,引入的目的主要是为了支持泛型。 Java的泛型体系还是比较复杂的, 不过没关系,本篇文章会从实战的角度来,学习泛型。 # 1...

真正的猛士,每天干一碗毒鸡汤!

问世间钱为何物,只叫人生死相许。!😄

# 一、Java泛型体系

Type 是 Java 语言中所有类型的公共父接口,其从 JDK5 开始引入,引入的目的主要是为了支持泛型。 Java的泛型体系还是比较复杂的, 不过没关系,本篇文章会从实战的角度来,学习泛型。

# 1.1 ParameterizedType 参数化泛型

ParameterizedType 是, 参数化泛型只要记住凡是带泛型的是明确的类型,只要不是数组GenericArrayType那么一定是ParameterizedType。 如下:

  • List<?> list 中的 list
  • Map<String,String> map中的map
  • Map<String,String> map中的map

# 1.1.1 API 说明

ParameterizedType 一共有3个方法如下。


    
  1. public interface ParameterizedType extends Type {
  2. // 获取泛型信息,输一个数组。因为可能泛型有多个
  3. Type[] getActualTypeArguments();
  4. // 原始数据类型
  5. Type getRawType();
  6. //
  7. Type getOwnerType();
  8. }
1 2 3 4 5 6 7 8
  • getRawType 获取原始数据类型
  • getActualTypeArguments 获取泛型信息,因为泛型可以是多个,所以返回是数组

# 1.1.2 代码示例


    
  1. public class Test {
  2. class Girl implements Person {}
  3. class Boy implements Person {}
  4. interface Person {}
  5. class School<A extends Boy & Person> {}
  6. School<Boy> boySchool;
  7. School<Boy>[] schools;
  8. @Test
  9. public void test() {
  10. // class java.lang.Class
  11. System.out.println(ReflectionUtils.findField(Test.class, "boy").getGenericType().getClass());
  12. // class sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
  13. System.out.println(ReflectionUtils.findField(Test.class, "boySchool").getGenericType().getClass());
  14. // class sun.reflect.generics.reflectiveObjects.GenericArrayTypeImpl
  15. System.out.println(ReflectionUtils.findField(Test.class, "schools").getGenericType().getClass());
  16. }
  17. }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
  • boy 是具体类型,且不是泛型,所以是Class类型
  • School<Boy> boySchool 是具体类型,但是有泛型<Boy>,所以是ParameterizedType
    • ParameterizedType#getActualTypeArguments 下标0就是泛型Boy
  • School<Boy>[] schools 是具体类型,有泛型<Boy>,但是是数组类型所以是GenericArrayType

# 1.2 GenericArrayType 泛型数组

GenericArrayTypeParameterizedType是比较类似的,唯一的区别是GenericArrayType一定是数组,如果不是数组就是ParameterizedType

# 1.2.1 API 说明

GenericArrayType 只提供了一个方法就是获取泛型的方法


    
  1. public interface GenericArrayType extends Type {
  2. // 获取数组泛型
  3. Type getGenericComponentType();
  4. }
1 2 3 4

# 1.2.2 代码示例


    
  1. public class Test {
  2. class Girl implements Person {}
  3. class Boy implements Person {}
  4. interface Person {}
  5. class School<A extends Boy & Person> {}
  6. School<Boy> boySchool;
  7. School<Boy>[] schools;
  8. @Test
  9. public void test2(){
  10. GenericArrayType schoolsArrayType = (GenericArrayType) ReflectionUtils.findField(Test.class, "schools").getGenericType();
  11. Type genericComponentType = schoolsArrayType.getGenericComponentType();
  12. // learn.common.print.Test$School<learn.common.print.Test$Boy>
  13. System.out.println(genericComponentType.getTypeName());
  14. // class sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
  15. System.out.println(genericComponentType.getClass());
  16. }
  17. }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
  • School<Boy> boySchool 是具体类型,且有泛型,但是不是数组所以是ParameterizedType
  • School<Boy>[] schools 是具体类型,且有泛型,但是数组所以就是GenericArrayType
    • GenericArrayType#getGenericComponentType = School<Boy> = ParameterizedType

# 1.3 TypeVariable 泛型变量

TypeVariable变量泛型是比较好判断的,只要是变量泛型。一定就是TypeVariable。

# 1.3.1 API 说明


    
  1. public interface TypeVariable<D extends GenericDeclaration> extends Type, AnnotatedElement {
  2. // 获取泛型信息
  3. Type[] getBounds();
  4. D getGenericDeclaration();
  5. String getName();
  6. AnnotatedType[] getAnnotatedBounds();
  7. }
1 2 3 4 5 6 7 8 9 10

# 1.3.2 代码示例


    
  1. class TypeVariableObj<A extends Number> {
  2. A a;
  3. TypeVariableObj<A> as;
  4. }
  5. @Test
  6. public void test3() {
  7. Type a = ReflectionUtils.findField(TypeVariableObj.class, "a").getGenericType();
  8. // class sun.reflect.generics.reflectiveObjects.TypeVariableImpl
  9. System.out.println(a.getClass());
  10. Type as = ReflectionUtils.findField(TypeVariableObj.class, "as").getGenericType();
  11. // class sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
  12. System.out.println(as.getClass());
  13. Type[] actualTypeArguments = ((ParameterizedType) as).getActualTypeArguments();
  14. // A 因为只有1个泛型,所以直接去下标0
  15. TypeVariable actualTypeArgument = (TypeVariable) actualTypeArguments[0];
  16. System.out.println(actualTypeArgument.getTypeName());
  17. }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
  • A a = TypeVariable
  • TypeVariableObj<A> as = ParameterizedType
    • ParameterizedType#getActualTypeArguments()[0] = <A>

# 1.4 WildcardType 泛型表达式

WildcardType也比较好判断只要是通配符,可以简单理解,直接带有 ? 的泛型限定那么就是 WildcardType

# 1.4.1 API 说明

WildcardType通配符, 如 ?, ? extends Number, ? super Integer


    
  1. public interface WildcardType extends Type {
  2. // 泛型上限
  3. Type[] getUpperBounds();
  4. // 泛型下限
  5. Type[] getLowerBounds();
  6. }
1 2 3 4 5 6
  • Type[] getUpperBounds(); //获得泛型表达式上界(上限) 获取泛型变量的上边界(extends)
  • Type[] getLowerBounds(); //获得泛型表达式下界(下限) 获取泛型变量的下边界(super)

# 1.4.2 代码示例


    
  1. public class WildcardTypeTest {
  2. Map<? extends String, ? super Number> map;
  3. @Test
  4. public void wildcardTypeTest() {
  5. Field map = ReflectionUtils.findField(WildcardTypeTest.class, "map");
  6. Type[] actualTypeArguments = ((ParameterizedType) map.getGenericType()).getActualTypeArguments();
  7. // ? extends java.lang.String
  8. System.out.println(((WildcardType) actualTypeArguments[0]).getTypeName());
  9. // class java.lang.String
  10. System.out.println(((WildcardType) actualTypeArguments[0]).getUpperBounds()[0]);
  11. }
  12. }
1 2 3 4 5 6 7 8 9 10 11 12
  • Map<? extends String, ? super Number> map 中 map是 ParameterizedType
    • ParameterizedType#getActualTypeArguments[0] = WildcardType#getUpperBounds[0] = String
    • ParameterizedType#getActualTypeArguments[1] = WildcardType#getLowerBounds[0] = Number

# 二、泛型获取

通过上面的学习,我们可以使用原始API来获取各种泛型的信息,而Spring中有一个比较好用的工具。屏蔽了底层的 具体实现。比较方便。

# 2.1 获取接口泛型


    
  1. class A {}
  2. class B {}
  3. interface School<T, K> {}
  4. interface X extends School<A, B> {}
  5. @Test
  6. public void test() {
  7. // 获取实现的接口是泛型的信息
  8. ResolvableType resolvableType = ResolvableType.forClass(X.class);
  9. Class<?> resolve1 = resolvableType.getInterfaces()[0].getGeneric(0).resolve();
  10. // class learn.common.print.ColorConsoleTest$A
  11. System.out.println(resolve1);
  12. Class<?> resolve2 = resolvableType.getInterfaces()[0].getGeneric(1).resolve();
  13. // class learn.common.print.ColorConsoleTest$B
  14. System.out.println(resolve2);
  15. }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

# 2.2 获取父类泛型


    
  1. class A {}
  2. class B {}
  3. class School<T, K> {}
  4. class X extends School<A, B> {}
  5. @Test
  6. public void test() {
  7. // 获取实现的接口是泛型的信息
  8. ResolvableType resolvableType = ResolvableType.forClass(X.class);
  9. Class<?> resolve1 = resolvableType.getSuperType().getGeneric(0).resolve();
  10. // class learn.common.print.ColorConsoleTest$A
  11. System.out.println(resolve1);
  12. Class<?> resolve2 = resolvableType.getSuperType().getGeneric(1).resolve();
  13. // class learn.common.print.ColorConsoleTest$B
  14. System.out.println(resolve2);
  15. }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

# 2.3 获取字段泛型


    
  1. class A {}
  2. class B {}
  3. class School<T, K> {}
  4. class X {
  5. private School<A, B> school;
  6. }
  7. @Test
  8. public void test() {
  9. // Spring的提供工具类,用于字段的泛型信息,Person<String>
  10. ResolvableType resolvableType = ResolvableType.forField(Objects.requireNonNull(ReflectionUtils.findField(X.class, "school")));
  11. System.out.println(resolvableType);
  12. Class<?> resolve1 = resolvableType.getGeneric(0).resolve();
  13. // class learn.common.print.ColorConsoleTest$A
  14. System.out.println(resolve1);
  15. Class<?> resolve2 = resolvableType.getGeneric(1).resolve();
  16. // class learn.common.print.ColorConsoleTest$B
  17. System.out.println(resolve2);
  18. }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

# 2.4 获取方法泛型


    
  1. class A {}
  2. class B {}
  3. class School<T, K> {}
  4. class X {
  5. public School<A, B> getSchool() {
  6. return null;
  7. }
  8. }
  9. @Test
  10. public void test() {
  11. // Spring的提供工具类,用于字段的泛型信息,Person<String>
  12. ResolvableType resolvableType = ResolvableType.forMethodReturnType(Objects.requireNonNull(ReflectionUtils.findMethod(X.class, "getSchool")));
  13. System.out.println(resolvableType);
  14. Class<?> resolve1 = resolvableType.getGeneric(0).resolve();
  15. // class learn.common.print.ColorConsoleTest$A
  16. System.out.println(resolve1);
  17. Class<?> resolve2 = resolvableType.getGeneric(1).resolve();
  18. // class learn.common.print.ColorConsoleTest$B
  19. System.out.println(resolve2);
  20. }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21

文章来源: springlearn.blog.csdn.net,作者:西魏陶渊明,版权归原作者所有,如需转载,请联系作者。

原文链接:springlearn.blog.csdn.net/article/details/125858147

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。