这几天看class类的代码,对泛型有了一点理解,在这里与大家分享一下。
首先我们来看一个非常简单的泛型
public class TestA<K extends List & Serilizable, V> { ... }
在这个类中<K extends List & Serilizable, V>称为泛型变量。
而K extends List & Serilizable的意思是K这个泛型是有上界的,它必须是一个继承List以及Serilizable的类或接口。
说完这些我们在来看看class类,class类继承的和泛型有关的接口有GenericDecalaration以及Type。
GenericDecalaration接口是说明哪些类的对象可以通过反射机制来获取泛型声明,它有三个实现类,分别是Cass, Constructor, Method。
可能我们会奇怪为什么没有Object类,那是因为Object类有一个
public final native Class<?> getClass();方法。
通过调用这个方法我们可以返回一个Class类型的对象
以下面这个例子为例:
public class Test { public static void main(String[] args) { Test t = new Test(); Class<? extends Test> c = t.getClass(); System.out.println(c.getName()); //输出Test } }
我们定义了一个Test类,然后生成了一个实例化对象t,通过getClass方法我们获得了t的运行时类对象c,这个是c就是Class类型的。我们试图将它输出到控制台,显示的结果正好就是Test——我们自定义的类的名称。
所以说每一个Object类的子类都可以通过getClass来获得其对应的运行时类对象。Class类实现了GenericDecalaration接口就约等于所有Object的子类都实现了GenericDecalaration接口了。
那么实现GenericDecalaration接口有什么用呢?GenericDecalaration接口有一个
public TypeVariable<?>[] getTypeParameters();方法
这个方法返回的泛型变量数组代表了泛型声明的内容,TypeVariable类型就是定义泛型变量的。
以下面这个例子为例:
public class Test<K extends List & Serializable, V> { public static void main(String[] args) { Test t = new Test(); TypeVariable[] tvarg = t.getClass().getTypeParameters(); System.out.println("tvarg.lenght=" + tvarg.length); //tvarg.lenght=2 } }
我们可以看到通过getTypeParameters方法返回了一个长度为2的数组,他们分别表示了
<K extends List & Serializable, V>
泛型变量中的
K和V(extends List & Serializable应该属于修饰)
从下面开始我们就要来分析一下泛型变量TypeVariable接口
TypeVariable总共有三个方法
Type[] getBounds();
D getGenericDeclaration();
String getName();
Type[] getBounds();方法很好理解,就是返回当前类型的边界,
以刚刚的例子为例K extends List & Serializable,那k的边界就应该是List和Serializable
用下面的例子来试验一下
public class Test<K extends List & Serializable, V> { public static void main(String[] args) { TypeVariable[] tvarg = new Test().getClass().getTypeParameters(); Type[] typearg = tvarg[0].getBounds(); System.out.println("typearg.lenght=" + typearg.length); for (int i = 0; i < typearg.length; i++) { System.out.println(typearg[i].toString()); } } }
我们看到控制台先输出了typearg.lenght=2说明有两个上边界。然后分别输出了两个边界的类型。
D getGenericDeclaration();方法则是返回在哪一个类上面进行了泛型的声明(我们看这个方法的名字直译是“获取通用声明”,但返回的却是一个在代码中具有声明的类的运行时类对象。我们可以这样理解,Class类型实现了GenericDeclaration接口,那我们要看声明的代码就要往这个Class上找,可以看成是一种提示吧。)
以下面的例子为例
public class Test<K extends List & Serializable, V> { public static void main(String[] args) { TypeVariable[] tvarg = new Test().getClass().getTypeParameters(); GenericDeclaration gd0 = tvarg[0].getGenericDeclaration(); GenericDeclaration gd1 = tvarg[1].getGenericDeclaration(); System.out.println("gd0=" + gd0.toString()); System.out.println("gd1=" + gd1.toString()); } }
在控制台直接显示了这个泛型是声明在Test这个类。
最后String getName();方法返回的是泛型变量的名称,就一刚刚那个例子为例,然后的就是K和V
public class Test<K extends List & Serializable, V> { public static void main(String[] args) { TypeVariable[] tvarg = new Test().getClass().getTypeParameters(); System.out.println("tvarg0=" + tvarg[0].getName()); System.out.println("tvarg1=" + tvarg[1].getName()); } }
通过这几个方法我们就可以利用反射机制来动态获取类型的泛型声明了。
相关推荐
GenericDeclaration 是 Java 中的公共接口,主要用于声明类型变量的实体。该接口的主要作用是提供一个统一的方式来定义和获取类型变量,以便在编程中提高代码的灵活性和可读性。在下面,我们将详细介绍 ...
目前实现GenericDeclaration接口的类包括Class、Method和Constructor,也就是说只能在这几种对象上进行泛型变量的声明。 类型变量的声明可以在类、方法和构造器上。例如,在类上声明类型变量可以这样写:class A<T>...
`Class` 类实现了几个接口:`Serializable`、`AnnotatedElement`、`GenericDeclaration` 和 `Type`。这些接口分别对应不同的功能: - `Serializable`:表明 `Class` 对象可以被序列化,允许我们保存和恢复其状态。 -...
在Java中,Class类实现了Serializable、GenericDeclaration、Type、AnnotatedElement等接口,这些接口使得Class对象能够被序列化、定义泛型信息、描述类型以及包含注解信息。由于Class对象的唯一性,可以使用“==”...
- `Class`对象实现了多个接口:`Serializable`, `GenericDeclaration`, `Type`, `AnnotatedElement`,这表明它可以被序列化,支持泛型声明,表示类型,并支持注解元数据。 - `Class`对象的私有构造器确保只能由JVM...
现在,你可以使用`@GenericDeclaration`、`@GenericSignatureFormat`和`@TypeParameter`等注解来提供更丰富的泛型信息。 5. **静态导入(Static Import)**:JDK 6允许开发者静态导入类的方法和常量,这样就可以...
9. **泛型**:讲解`java.lang.reflect.ParameterizedType`和`java.lang.reflect.GenericDeclaration`等接口,揭示泛型在编译期和运行期的行为差异。 10. **日期时间API**:对比旧的`java.util.Date`和`java.util....