Java Reflection(九):泛型

内容索引
运用泛型反射的经验法则
泛型方法返回类型
泛型方法参数类型
泛型变量类型

我常常在一些文章以及论坛中读到说Java泛型信息在编译期被擦除(erased)所以你无法在运行期获得有关泛型的信息。其实这种说法并不完全正确的,在一些情况下是可以在运行期获取到泛型的信息。这些情况其实覆盖了一些我们需要泛型信息的需求。在本节中我们会演示一下这些情况。

运用泛型反射的经验法则

下面是两个典型的使用泛型的场景:
1、声明一个需要被参数化(parameterizable)的类/接口。
2、使用一个参数化类。

当你声明一个类或者接口的时候你可以指明这个类或接口可以被参数化,java.util.List接口就是典型的例子。你可以运用泛型机制创建一个标明存储的是String类型list,这样比你创建一个Object的list要更好。

当你想在运行期参数化类型本身,比如你想检查java.util.List类的参数化类型,你是没有办法能知道他具体的参数化类型是什么。这样一来这个类型就可以是一个应用中所有的类型。但是,当你检查一个使用了被参数化的类型的变量或者方法,你可以获得这个被参数化类型的具体参数。总之:

你不能在运行期获知一个被参数化的类型的具体参数类型是什么,但是你可以在用到这个被参数化类型的方法以及变量中找到他们,换句话说就是获知他们具体的参数化类型。
在下面的段落中会向你演示这类情况。

泛型方法返回类型

如果你获得了java.lang.reflect.Method对象,那么你就可以获取到这个方法的泛型返回类型信息。如果方法是在一个被参数化类型之中(译者注:如T fun())那么你无法获取他的具体类型,但是如果方法返回一个泛型类(译者注:如List fun())那么你就可以获得这个泛型类的具体参数化类型。你可以在“Java Reflection: Methods”中阅读到有关如何获取Method对象的相关内容。下面这个例子定义了一个类这个类中的方法返回类型是一个泛型类型:

  public class MyClass {

  protected List<String> stringList = ...;

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

我们可以获取getStringList()方法的泛型返回类型,换句话说,我们可以检测到getStringList()方法返回的是List而不仅仅只是一个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类的实例。Class类实现了Type接口。

泛型方法参数类型

你同样可以通过反射来获取方法参数的泛型类型,下面这个例子定义了一个类,这个类中的方法的参数是一个被参数化的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类的实例。Class类实现了Type接口。

泛型变量类型

同样可以通过反射来访问公有(Public)变量的泛型类型,无论这个变量是一个类的静态成员变量或是实例成员变量。你可以在“Java Reflection: 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[]数组fieldArgClass只有一个结果 – 一个代表java.lang.String的Class类的实例。Class类实现了Type接口。

时间: 2024-11-03 18:50:27

Java Reflection(九):泛型的相关文章

Java Reflection API简介

Java Reflection API提供对JVM中的类,接口和对象的深入洞察.开发者通常使用API来完成以下的任务,这解释了为什么总是使用开发工具,例如debugger和Integrated Development Environments (IDEs): · 决定一个对象的类. · 获得关于一个类的modifiers, fields, methods, constructors, etc的信息. · 获得关于一个接口的常量和方法声明. · 创建一个类的instance,这个类的名字直到运行时

java基础-java中的泛型的具体作用是什么?

问题描述 java中的泛型的具体作用是什么? 看了很多教程,用到泛型的地方很多,最不明白的就是泛型的存在是因为什么,怎么用,什么时候用,求大神

java 泛型 类型擦除-Java 核心技术中泛型的使用

问题描述 Java 核心技术中泛型的使用 在看Java核心技术的过程中有个问题不明白,求各位大神指导. 书中写到: 不能构造一个泛型数组: public static T[] minmax(T[] a) { T[] mm = new T(2); ... } 书中的解释是类型擦除会让这个方法永远构造Object[2]数组. 什么叫永远构造Object[2]数组?是死循环?还是说构造的是Object[2]数组而不是T[2]数组 解决方案 说构造的是Object[2]数组而不是T[2]数组

Java学习之——泛型

1.概要 generics enable types (classes and interfaces) to be parameters when defining classes, interfaces and methods. 泛型能在定义类,接口和方法时将类型(类和接口)作为参数.和方法声明时的形式参数很类似,都是为了在不同的输入时重用相同的代码.不同的是 形式参数输入的是值而泛型是类型. 2.为什么使用泛型 1.编译时更加强的(Stronger)类型检测 java编译器对泛型代码进行强类

java se-使用泛型打印输出任意类型的数组,为什么调用时有错误?

问题描述 使用泛型打印输出任意类型的数组,为什么调用时有错误? import java.util.Arrays; public class FanXing { public static void printMatrix(T[][] matrix){ for(int i=0;i<matrix.length;i++){ System.out.println(Arrays.toString(matrix[i])); } } public static void main(String[] args)

利用Java Reflection(反射)原理,在hibernate里面实现对单表、视图的动态组合查询

动态|视图|组合查询     Reflection 是 Java 程序开发语言的特征之一,它允许运行中的程序对自身进行访问,并能直接操作程序的内部属性.     Hibernate是一个面向Java环境的对象/关系数据库映射工具,基本上,每个表或者视图在hibernate里面都可以对应一个类,在此处,我们通过充分的利用这个类,来实现动态组合查询. 首先我们一起来看看这个函数的源代码:     /**     * 组合查询     * @param object 包含查询条件的对象     * @

java基础之泛型

泛型 术语 "?"通配符 通配符的扩展 自定义泛型方法 "擦除"实例 类型参数的类型推断 自定义泛型类 泛型方法和泛型类的比较 泛型和反射 通过反射获得泛型的实际类型参数 本文对泛型的基本知识进行较为全面的总结,并附上简短的代码实例,加深记忆. 泛型 将集合中的元素限定为一个特定的类型. 术语 ArrayList<E> -- 泛型类型 ArrayList -- 原始类型 E -- 类型参数 <> -- 读作"typeof"

将java类的泛型集合转换成json对象

一般用extjs开发传输都是用json比较多,这个将来大家也许会用到... ConvertJsonUtils.java package com.sunweb.util.jsonfactory; import java.util.List; import com.sunweb.util.jsonfactory.jsontools.JSONArray;import com.sunweb.util.jsonfactory.jsontools.JSONException;import com.sunwe

Java Reflection(十二):动态类加载与重载

原文地址作者: Jakob Jenkov 译者:叶文海(yewenhai@gmail.com) 内容索引类加载器类加载体系类加载动态类加载动态类重载自定义类重载类加载/重载示例 Java允许你在运行期动态加载和重载类,但是这个功能并没有像人们希望的那么简单直接.这篇文章将阐述在Java中如何加载以及重载类. 你可能会质疑为什么Java动态类加载特性是Java反射机制的一部分而不是Java核心平台的一部分.不管怎样,这篇文章被放到了Java反射系列里面而且也没有更好的系列来包含它了. 类加载器 所