Java反射 - 泛型

简介: 使用Java泛型通常分为两种不同的情况:声明一个类/接口是可参数化的。使用可参数化的类。当你写一个类或接口时,你可以指定它应该是可参数化的。 java.util.List接口就是这种情况。

使用Java泛型通常分为两种不同的情况:

  1. 声明一个类/接口是可参数化的。
  2. 使用可参数化的类。
    当你写一个类或接口时,你可以指定它应该是可参数化的。 java.util.List接口就是这种情况。 而不是创建一个Object列表,你可以参数化java.util.List来创建一个String String列表,如下所示:
List<String> myList = new ArrayList<String>();

当通过反射在运行时检查可参数化类型本身时,如java.util.List,无法知道类型已经被参数化。对象本身不知道它被参数化了什么。

但是,该对象的引用知道包含它所引用的泛型的类型。也就是说,如果它不是一个局部变量。如果对象被对象中的字段引用,则可以通过反射来查看Field声明,以获取有关由该字段声明的泛型类型的信息。

如果对象被方法中的参数引用,也是一样的。通过该方法的Parameter对象(一个Java反射对象),您可以看到声明了哪个泛型类型的参数。

最后,您还可以查看方法的返回类型,以查看它声明的泛型类型。同样,你不能从返回的实际对象中看到它。您需要通过反射来查看方法声明,以查看它声明的返回类型(包括泛型)。

综上所述:只能从引用的声明(字段,参数,返回类型)中看到这些引用引用的对象所具有的通用类型。你不能从对象本身看到它。

以下各节将仔细研究这些情况。

泛型方法返回类型

如果已经获得java.lang.reflect.Method对象,则可以获取有关其通用返回类型的信息。 您可以阅读如何获取文本“Java泛型:方法”中的Method对象。 下面是一个带有参数化返回类型的方法的示例类:

public class MyClass {

  protected List<String> stringList = ...;

  public List<String> getStringList(){
    return this.stringList;
  }
}

在这个类中,可以获得getStringList()方法的通用返回类型。 换句话说,可以检测到getStringList()返回一个List <String>而不仅仅是一个List。

Method method = MyClass.class.getMethod("getStringList", null);

Type returnType = method.getGenericReturnType();

if(returnType instanceof ParameterizedType){
    ParameterizedType type = (ParameterizedType) returnType;
    Type[] typeArguments = type.getActualTypeArguments();
    for(Type typeArgument : typeArguments){
        Class typeArgClass = (Class) typeArgument;
        System.out.println("typeArgClass = " + typeArgClass);
    }
}

这段代码将打印出“typeArgClass = java.lang.String”文本。 Type []数组typeArguments数组将包含一个项目 - 一个表示java.lang.String类的Class实例。 类实现了Type接口。

泛型方法参数类型

您也可以通过Java Reflection在运行时访问通用类型的参数类型。 下面是一个带有参数化List作为参数的方法的示例类:

public class MyClass {
  protected List<String> stringList = ...;

  public void setStringList(List<String> list){
    this.stringList = list;
  }
}
method = Myclass.class.getMethod("setStringList", List.class);

Type[] genericParameterTypes = method.getGenericParameterTypes();

for(Type genericParameterType : genericParameterTypes){
    if(genericParameterType instanceof ParameterizedType){
        ParameterizedType aType = (ParameterizedType) genericParameterType;
        Type[] parameterArgTypes = aType.getActualTypeArguments();
        for(Type parameterArgType : parameterArgTypes){
            Class parameterArgClass = (Class) parameterArgType;
            System.out.println("parameterArgClass = " + parameterArgClass);
        }
    }
}

这段代码将打印出“parameterArgType = java.lang.String”文本。 Type []数组的parameterArgTypes数组将包含一个项 - 一个表示类java.lang.String的Class实例。 类实现了Type接口。

通用字段类型

也可以访问通用类型的公共字段。 字段是类成员变量 - 静态或实例变量。 您可以阅读关于在文本“Java Generics:Fields”中获取Field对象的信息。 这是前面的例子,带有一个名为stringList的实例字段。

public class MyClass {
  public List<String> stringList = ...;
}
Field field = MyClass.class.getField("stringList");

Type genericFieldType = field.getGenericType();

if(genericFieldType instanceof ParameterizedType){
    ParameterizedType aType = (ParameterizedType) genericFieldType;
    Type[] fieldArgTypes = aType.getActualTypeArguments();
    for(Type fieldArgType : fieldArgTypes){
        Class fieldArgClass = (Class) fieldArgType;
        System.out.println("fieldArgClass = " + fieldArgClass);
    }
}

这段代码将打印出“fieldArgClass = java.lang.String”文本。 Type []数组fieldArgTypes数组将包含一个项目 - 一个表示类java.lang.String的Class实例。 类实现了Type接口.

实战

package com.reflection.detail;

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

/**
 * 反射泛型
 * Created by Fant.J.
 * 2018/2/7 16:31
 */
public class Reflection_Generics {
    public static void main(String[] args) throws NoSuchMethodException {

        Class aClass = People.class;
        Method getStringList = aClass.getMethod("getStringList", null);
        //获取方法的返回值类型
        Type returnType = getStringList.getGenericReturnType();
        System.out.println(returnType);

        if(returnType instanceof ParameterizedType){
            ParameterizedType type = (ParameterizedType) returnType;
            Type[] typeArguments = type.getActualTypeArguments();
            for(Type typeArgument : typeArguments){
                Class typeArgClass = (Class) typeArgument;
                System.out.println("typeArgClass = " + typeArgClass);
            }
        }

    }
}

java.util.List<java.lang.String>
typeArgClass = class java.lang.String
相关文章
|
12月前
|
安全 Java
Java之泛型使用教程
Java之泛型使用教程
528 10
|
安全 Java API
在Java中识别泛型信息
以上步骤和示例代码展示了怎样在Java中获取泛型类、泛型方法和泛型字段的类型参数信息。这些方法利用Java的反射API来绕过类型擦除的限制并访问运行时的类型信息。这对于在运行时进行类型安全的操作是很有帮助的,比如在创建类型安全的集合或者其他复杂数据结构时处理泛型。注意,过度使用反射可能会导致代码难以理解和维护,因此应该在确有必要时才使用反射来获取泛型信息。
395 11
|
安全 Java 索引
Java——反射&枚举
本文介绍了Java反射机制及其应用,包括获取Class对象、构造方法、成员变量和成员方法。反射允许在运行时动态操作类和对象,例如创建对象、调用方法和访问字段。文章详细解释了不同方法的使用方式及其注意事项,并展示了如何通过反射获取类的各种信息。此外,还介绍了枚举类型的特点和使用方法,包括枚举的构造方法及其在反射中的特殊处理。
409 10
Java——反射&枚举
|
Java 数据库连接 Spring
反射-----浅解析(Java)
在java中,我们可以通过反射机制,知道任何一个类的成员变量(成员属性)和成员方法,也可以堆任何一个对象,调用这个对象的任何属性和方法,更进一步我们还可以修改部分信息和。
|
Java 编译器 容器
Java——包装类和泛型
包装类是Java中一种特殊类,用于将基本数据类型(如 `int`、`double`、`char` 等)封装成对象。这样做可以利用对象的特性和方法。Java 提供了八种基本数据类型的包装类:`Integer` (`int`)、`Double` (`double`)、`Byte` (`byte`)、`Short` (`short`)、`Long` (`long`)、`Float` (`float`)、`Character` (`char`) 和 `Boolean` (`boolean`)。包装类可以通过 `valueOf()` 方法或自动装箱/拆箱机制创建。
337 9
Java——包装类和泛型
|
安全 Java API
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
String常量池、String、StringBuffer、Stringbuilder有什么区别、List与Set的区别、ArrayList和LinkedList的区别、HashMap底层原理、ConcurrentHashMap、HashMap和Hashtable的区别、泛型擦除、ABA问题、IO多路复用、BIO、NIO、O、异常处理机制、反射
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
|
监控 Java
Java基础——反射
本文介绍了Java反射机制的基本概念和使用方法,包括`Class`类的使用、动态加载类、获取方法和成员变量信息、方法反射操作、以及通过反射了解集合泛型的本质。同时,文章还探讨了动态代理的概念及其应用,通过实例展示了如何利用动态代理实现面向切面编程(AOP),例如为方法执行添加性能监控。
283 5
|
Java
Java的反射
Java的反射。
300 2
|
Java 语音技术 容器
java数据结构泛型
java数据结构泛型
310 5
|
安全 Java 测试技术
🌟Java零基础-反射:从入门到精通
【10月更文挑战第4天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
364 2