反射相关的类和接口简介
在Java.lang.reflect
包中定义了一些接口和类,简单记录下他们的作用
相关类说明
这些类都比较简单,对照API一看就懂,主要是平时用到的比较少,这里先简单说明下,不在此展开
类 | 说明 |
---|---|
AccessibleObject | Field、Method 和Constructor 对象的基类 |
Field | final类, 对应类或接口的单个字段 |
Method | final类, 对应类或接口的单独某个方法 |
Constructor<T> | final类, 对应类的单个构造方法 |
Modifier | 对应类和成员访问修饰符, 如public,static,final,native,synchronized 等 |
Array | final类, 对应数组 |
Proxy | 提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类 |
ReflectPermission | final类, 反射操作的Permission 类 |
另外反射机制还经常用到java.lang
中的类, 如Class
、Packate
还有各种原始类型等
相关接口继承关系图
相关接口说明
这里先简单介绍下,后文还会详细说明这些接口
接口 | 说明 |
---|---|
AnnotatedElement | 被注解标注的元素都实现的接口 实现类有 AccessibleObject 及其子类,Class Package |
Member | 成员接口, 反映字段、方法、构造函数的信息 |
Type | 所有类型的父接口, 之后的文章会详细介绍 |
GenericDeclaration | 各种声明类型的父接口, 如Class,Constructor,Method |
TypeVariable<D extends GenericDeclaration> | 类型变量类型 |
ParameterizedType | 参数化类型, 如Collection<String> |
GenericArrayType | 数组类型, 它里面的元素为参数化类型或类型变量(上面那俩) |
WildcardType | 通配符类型, 如<?>, <? extends Number>, <? super Integer> |
InvocationHandler | 代理处理器接口 |
Object
, Class
和Type
的关系和区别
所有的类都继承Object
是毫无疑问的, Class
也是类,也继承Object
Class
类特殊的地方是它在运行时用来描述类的各种元信息,对象是类的实例,而类在运行时的描述就是Class
Type
是个接口,用来表示某个对象是什么类型的,Class
类实现了好几个接口,其中一个就是Type
后面的文章内容更能体现出区别来
反射的具体功能
反射作用挺多, 比如反编译, 通过反射机制访问对象的属性、方法、构造方法等, 先简单给出一些示例
获取类
有如下三种方法:
- 通过
Class.forName()
, 如:Class clazz = Class.forName("java.lang.String");
- 通过类的
class
属性, 如:Class clazz = String.class;
- 通过实例对象的
getClass
方法, 如:Class clazz = user.getClass();
获取对象实例
- 通过
Class
实例的newInstance()
, 如:String str = (String)clazz.newInstance();
反射相关接口的详细说明
这些接口的关系可参考上面那幅图, 这里只详细说明AnnotatedElement、Member、InvocationHandler、GenericDeclaration
这几个接口
Type
接口及其字类在Type详解中详细说明
AnnotatedElement
这个接口最简单, 实现了该接口的类都能添加注解, 其实现类有: AccessibleObject, Class, Constructor, Field, Method, Package
它有如下方法:
boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)
: 该类上是否存在annotationClass
这个注解Annotation[] getAnnotations()
: 获取这个元素上的所有注解(包括父类上被@Inherited
标记的注解)<A extends Annotation> A getAnnotation(Class<A> annotationClass)
: 获取这个元素上指定类型的注解, 没有返回nullAnnotation[] getDeclaredAnnotations()
: 获取直接标注在这个元素上的注解
Member
表示组成类的成员, 其实现类有: Constructor, Field, Method
它有如下方法:
boolean isSynthetic()
: 是否是复合类int getModifiers()
: 以数字形式返回修饰符String getName()
: 返回成员的简单名, 如: 属性名字, 方法名字(只有名字,不包括参数), 构造器名字Class<?> getDeclaringClass()
: 返回声明该成员的声明类
<code style="font-family: Monaco, "Bitstream Vera Sans Mono", "Lucida Console", Terminal; overflow-x: auto;"><span class="c1" style="color: rgb(117, 113, 94);">// getName方法的测试</span>
<span class="kn" style="color: rgb(249, 38, 114);">package</span> <span class="n">com</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">test</span><span class="o" style="color: rgb(249, 38, 114);">;</span>
<span class="kd" style="color: rgb(102, 217, 239);">public</span> <span class="kd" style="color: rgb(102, 217, 239);">class</span> <span class="nc" style="color: rgb(166, 226, 46);">TestMember</span> <span class="o" style="color: rgb(249, 38, 114);">{</span>
<span class="kd" style="color: rgb(102, 217, 239);">private</span> <span class="n">String</span> <span class="n">name</span><span class="o" style="color: rgb(249, 38, 114);">;</span> <span class="c1" style="color: rgb(117, 113, 94);">// 属性名为: name</span>
<span class="kd" style="color: rgb(102, 217, 239);">public</span> <span class="kt" style="color: rgb(102, 217, 239);">void</span> <span class="n">hello</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">String</span> <span class="n">name</span><span class="o" style="color: rgb(249, 38, 114);">)</span> <span class="o" style="color: rgb(249, 38, 114);">{}</span> <span class="c1" style="color: rgb(117, 113, 94);">// 方法名(不包括参数)为: hello</span>
<span class="kd" style="color: rgb(102, 217, 239);">public</span> <span class="n">TestMember</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">String</span> <span class="n">name</span><span class="o" style="color: rgb(249, 38, 114);">)</span> <span class="o" style="color: rgb(249, 38, 114);">{}</span> <span class="c1" style="color: rgb(117, 113, 94);">// 构造器名为: com.test.TestMember</span>
<span class="kd" style="color: rgb(102, 217, 239);">public</span> <span class="kd" style="color: rgb(102, 217, 239);">static</span> <span class="kt" style="color: rgb(102, 217, 239);">void</span> <span class="n">main</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">String</span><span class="o" style="color: rgb(249, 38, 114);">[]</span> <span class="n">args</span><span class="o" style="color: rgb(249, 38, 114);">)</span> <span class="kd" style="color: rgb(102, 217, 239);">throws</span> <span class="n">Exception</span> <span class="o" style="color: rgb(249, 38, 114);">{</span>
<span class="n">System</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">out</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">println</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">TestMember</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">class</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getDeclaredField</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="s" style="color: rgb(230, 219, 116);">"name"</span><span class="o" style="color: rgb(249, 38, 114);">).</span><span class="na" style="color: rgb(166, 226, 46);">getName</span><span class="o" style="color: rgb(249, 38, 114);">());</span> <span class="c1" style="color: rgb(117, 113, 94);">// name</span>
<span class="n">System</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">out</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">println</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">TestMember</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">class</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getDeclaredMethod</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="s" style="color: rgb(230, 219, 116);">"hello"</span><span class="o" style="color: rgb(249, 38, 114);">,</span> <span class="n">String</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">class</span><span class="o" style="color: rgb(249, 38, 114);">).</span><span class="na" style="color: rgb(166, 226, 46);">getName</span><span class="o" style="color: rgb(249, 38, 114);">());</span> <span class="c1" style="color: rgb(117, 113, 94);">// hello</span>
<span class="n">System</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">out</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">println</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">TestMember</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">class</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getDeclaredConstructor</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">String</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">class</span><span class="o" style="color: rgb(249, 38, 114);">).</span><span class="na" style="color: rgb(166, 226, 46);">getName</span><span class="o" style="color: rgb(249, 38, 114);">());</span> <span class="c1" style="color: rgb(117, 113, 94);">//com.test.TestMember</span>
<span class="n">System</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">out</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">println</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">TestMember</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">class</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getDeclaredField</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="s" style="color: rgb(230, 219, 116);">"name"</span><span class="o" style="color: rgb(249, 38, 114);">).</span><span class="na" style="color: rgb(166, 226, 46);">getDeclaringClass</span><span class="o" style="color: rgb(249, 38, 114);">().</span><span class="na" style="color: rgb(166, 226, 46);">getName</span><span class="o" style="color: rgb(249, 38, 114);">());</span><span class="c1" style="color: rgb(117, 113, 94);">//com.test.TestMember</span>
<span class="o" style="color: rgb(249, 38, 114);">}</span>
<span class="o" style="color: rgb(249, 38, 114);">}</span>
</code>
InvocationHandler
代理处理器类的实例需要实现的接口, 只有一个方法:
Object invoke(Object proxy, Method method, Object[] args)
: 代理对象执行方法时真正调用的函数
其中:
Object proxy
: 表示代理对象(比如通过Proxy.newProxyInstance()
得到的对象), 不是实现了该接口的代理处理器对象Method method
: 被代理对象的方法, 就是接口原来实现类里的方法, 代理对象执行的时候会调用被代理对象的方法(取决于代码怎么写)Object[] args
: 上面那个方法需要的参数
通常代理处理器类的实例handler
会作为参数传到java代理类Proxy
的newProxyInstance
方法中来产生一个代理对象(与被代理对象实现了同一接口)
调用代理对象的方法时, 真正调用的就是上面的invoke函数.
还是来个例子吧(HelloImpl
实现了Hello
接口, 并实现了sayHello()
方法)
<code style="font-family: Monaco, "Bitstream Vera Sans Mono", "Lucida Console", Terminal; overflow-x: auto;"><span class="c1" style="color: rgb(117, 113, 94);">// 代理处理器类</span>
<span class="kd" style="color: rgb(102, 217, 239);">public</span> <span class="kd" style="color: rgb(102, 217, 239);">class</span> <span class="nc" style="color: rgb(166, 226, 46);">AOPHandler</span> <span class="kd" style="color: rgb(102, 217, 239);">implements</span> <span class="n">InvocationHandler</span> <span class="o" style="color: rgb(249, 38, 114);">{</span>
<span class="kd" style="color: rgb(102, 217, 239);">private</span> <span class="n">Object</span> <span class="n">target</span><span class="o" style="color: rgb(249, 38, 114);">;</span> <span class="c1" style="color: rgb(117, 113, 94);">// 这个用来表示被代理的对象</span>
<span class="kd" style="color: rgb(102, 217, 239);">public</span> <span class="n">AOPHandler</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">Object</span> <span class="n">target</span><span class="o" style="color: rgb(249, 38, 114);">)</span> <span class="o" style="color: rgb(249, 38, 114);">{</span>
<span class="k" style="color: rgb(102, 217, 239);">this</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">target</span> <span class="o" style="color: rgb(249, 38, 114);">=</span> <span class="n">target</span><span class="o" style="color: rgb(249, 38, 114);">;</span>
<span class="o" style="color: rgb(249, 38, 114);">}</span>
<span class="kd" style="color: rgb(102, 217, 239);">public</span> <span class="n">Object</span> <span class="n">invoke</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">Object</span> <span class="n">proxy</span><span class="o" style="color: rgb(249, 38, 114);">,</span> <span class="n">Method</span> <span class="n">method</span><span class="o" style="color: rgb(249, 38, 114);">,</span> <span class="n">Object</span><span class="o" style="color: rgb(249, 38, 114);">[]</span> <span class="n">args</span><span class="o" style="color: rgb(249, 38, 114);">)</span> <span class="kd" style="color: rgb(102, 217, 239);">throws</span> <span class="n">Throwable</span> <span class="o" style="color: rgb(249, 38, 114);">{</span>
<span class="n">System</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">out</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">println</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="s" style="color: rgb(230, 219, 116);">"proxy:"</span> <span class="o" style="color: rgb(249, 38, 114);">+</span> <span class="n">proxy</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getClass</span><span class="o" style="color: rgb(249, 38, 114);">().</span><span class="na" style="color: rgb(166, 226, 46);">getName</span><span class="o" style="color: rgb(249, 38, 114);">());</span> <span class="c1" style="color: rgb(117, 113, 94);">// proxy:com.sun.proxy.$Proxy0</span>
<span class="n">System</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">out</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">println</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="s" style="color: rgb(230, 219, 116);">"method:"</span> <span class="o" style="color: rgb(249, 38, 114);">+</span> <span class="n">method</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getClass</span><span class="o" style="color: rgb(249, 38, 114);">().</span><span class="na" style="color: rgb(166, 226, 46);">getName</span><span class="o" style="color: rgb(249, 38, 114);">());</span> <span class="c1" style="color: rgb(117, 113, 94);">// proxy:java.lang.reflect.Method</span>
<span class="k" style="color: rgb(102, 217, 239);">return</span> <span class="n">method</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">invoke</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">target</span><span class="o" style="color: rgb(249, 38, 114);">,</span> <span class="n">args</span><span class="o" style="color: rgb(249, 38, 114);">);</span> <span class="c1" style="color: rgb(117, 113, 94);">// 调用被代理对象的的方法, 即 target 的 method</span>
<span class="o" style="color: rgb(249, 38, 114);">}</span>
<span class="o" style="color: rgb(249, 38, 114);">}</span>
<span class="c1" style="color: rgb(117, 113, 94);">// 测试类</span>
<span class="kd" style="color: rgb(102, 217, 239);">public</span> <span class="kd" style="color: rgb(102, 217, 239);">class</span> <span class="nc" style="color: rgb(166, 226, 46);">ProxyTest</span> <span class="o" style="color: rgb(249, 38, 114);">{</span>
<span class="kd" style="color: rgb(102, 217, 239);">public</span> <span class="kd" style="color: rgb(102, 217, 239);">static</span> <span class="kt" style="color: rgb(102, 217, 239);">void</span> <span class="n">main</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">String</span><span class="o" style="color: rgb(249, 38, 114);">[]</span> <span class="n">args</span><span class="o" style="color: rgb(249, 38, 114);">)</span> <span class="kd" style="color: rgb(102, 217, 239);">throws</span> <span class="n">Exception</span> <span class="o" style="color: rgb(249, 38, 114);">{</span>
<span class="n">Object</span> <span class="n">obj</span> <span class="o" style="color: rgb(249, 38, 114);">=</span> <span class="n">Class</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">forName</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="s" style="color: rgb(230, 219, 116);">"com.test.HelloImpl"</span><span class="o" style="color: rgb(249, 38, 114);">).</span><span class="na" style="color: rgb(166, 226, 46);">newInstance</span><span class="o" style="color: rgb(249, 38, 114);">();</span>
<span class="n">InvocationHandler</span> <span class="n">handler</span> <span class="o" style="color: rgb(249, 38, 114);">=</span> <span class="k" style="color: rgb(102, 217, 239);">new</span> <span class="n">AOPHandler</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">obj</span><span class="o" style="color: rgb(249, 38, 114);">);</span> <span class="c1" style="color: rgb(117, 113, 94);">// 创建代理处理器对象的时候把被代理的对象传进去</span>
<span class="c1" style="color: rgb(117, 113, 94);">// 这里生成代理类对象, 参数依次为: 被代理对象的ClassLoader, 被代理对象实现的所有接口, 代理处理器</span>
<span class="n">Hello</span> <span class="n">proxy</span> <span class="o" style="color: rgb(249, 38, 114);">=</span> <span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">Hello</span><span class="o" style="color: rgb(249, 38, 114);">)</span> <span class="n">Proxy</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">newProxyInstance</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">obj</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getClass</span><span class="o" style="color: rgb(249, 38, 114);">().</span><span class="na" style="color: rgb(166, 226, 46);">getClassLoader</span><span class="o" style="color: rgb(249, 38, 114);">(),</span> <span class="n">obj</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getClass</span><span class="o" style="color: rgb(249, 38, 114);">().</span><span class="na" style="color: rgb(166, 226, 46);">getInterfaces</span><span class="o" style="color: rgb(249, 38, 114);">(),</span> <span class="n">handler</span><span class="o" style="color: rgb(249, 38, 114);">);</span>
<span class="n">proxy</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">sayHello</span><span class="o" style="color: rgb(249, 38, 114);">();</span> <span class="c1" style="color: rgb(117, 113, 94);">// 这就调用了那个invoke方法</span>
<span class="o" style="color: rgb(249, 38, 114);">}</span>
<span class="o" style="color: rgb(249, 38, 114);">}</span>
</code>
GenericDeclaration
可以声明类型变量的实体的公共接口, 就是那些能够声明范型类型<T>
的地方, 注意是声明而不是使用.其实现类有: Class, Constructor, Method
它就一个方法:
TypeVariable<?>[] getTypeParameters()
: 按照声明顺序返回声明的类型变量
对它可以这么理解:
在定义类或方法时, 我们一般可以声明范型, 如<T> T getData()
, 因此可以声明这些<T>、<F>
的实体, 都实现了该接口;
而那些声明出来的T、F
叫类型变量(TypeVariable
), 后面会说到.
下面就把Type
的来龙去脉彻底弄清楚
Type
Type
是所有类型的父接口, 如原始类型(raw types,对应Class)、 参数化类型(parameterized types, 对应ParameterizedType)、 数组类型(array types,对应GenericArrayType)、 类型变量(type variables, 对应TypeVariable)和基本(原生)类型(primitive types, 对应Class), 子接口有ParameterizedType, TypeVariable<D>, GenericArrayType, WildcardType
, 实现类有Class
ParameterizedType
具体的范型类型, 如Map<String, String>
有如下方法:
Type getRawType()
: 返回承载该泛型信息的对象, 如上面那个Map<String, String>
承载范型信息的对象是Map
Type[] getActualTypeArguments()
: 返回实际泛型类型列表, 如上面那个Map<String, String>
实际范型列表中有两个元素, 都是String
Type getOwnerType()
: 返回是谁的member.(上面那两个最常用)
<code style="font-family: Monaco, "Bitstream Vera Sans Mono", "Lucida Console", Terminal; overflow-x: auto;"><span class="kd" style="color: rgb(102, 217, 239);">public</span> <span class="kd" style="color: rgb(102, 217, 239);">class</span> <span class="nc" style="color: rgb(166, 226, 46);">TestType</span> <span class="o" style="color: rgb(249, 38, 114);">{</span>
<span class="n">Map</span><span class="o" style="color: rgb(249, 38, 114);"><</span><span class="n">String</span><span class="o" style="color: rgb(249, 38, 114);">,</span> <span class="n">String</span><span class="o" style="color: rgb(249, 38, 114);">></span> <span class="n">map</span><span class="o" style="color: rgb(249, 38, 114);">;</span>
<span class="kd" style="color: rgb(102, 217, 239);">public</span> <span class="kd" style="color: rgb(102, 217, 239);">static</span> <span class="kt" style="color: rgb(102, 217, 239);">void</span> <span class="n">main</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">String</span><span class="o" style="color: rgb(249, 38, 114);">[]</span> <span class="n">args</span><span class="o" style="color: rgb(249, 38, 114);">)</span> <span class="kd" style="color: rgb(102, 217, 239);">throws</span> <span class="n">Exception</span> <span class="o" style="color: rgb(249, 38, 114);">{</span>
<span class="n">Field</span> <span class="n">f</span> <span class="o" style="color: rgb(249, 38, 114);">=</span> <span class="n">TestType</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">class</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getDeclaredField</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="s" style="color: rgb(230, 219, 116);">"map"</span><span class="o" style="color: rgb(249, 38, 114);">);</span>
<span class="n">System</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">out</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">println</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">f</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getGenericType</span><span class="o" style="color: rgb(249, 38, 114);">());</span> <span class="c1" style="color: rgb(117, 113, 94);">// java.util.Map<java.lang.String, java.lang.String></span>
<span class="n">System</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">out</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">println</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">f</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getGenericType</span><span class="o" style="color: rgb(249, 38, 114);">()</span> <span class="k" style="color: rgb(102, 217, 239);">instanceof</span> <span class="n">ParameterizedType</span><span class="o" style="color: rgb(249, 38, 114);">);</span> <span class="c1" style="color: rgb(117, 113, 94);">// true</span>
<span class="n">ParameterizedType</span> <span class="n">pType</span> <span class="o" style="color: rgb(249, 38, 114);">=</span> <span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">ParameterizedType</span><span class="o" style="color: rgb(249, 38, 114);">)</span> <span class="n">f</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getGenericType</span><span class="o" style="color: rgb(249, 38, 114);">();</span>
<span class="n">System</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">out</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">println</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">pType</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getRawType</span><span class="o" style="color: rgb(249, 38, 114);">());</span> <span class="c1" style="color: rgb(117, 113, 94);">// interface java.util.Map</span>
<span class="k" style="color: rgb(102, 217, 239);">for</span> <span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">Type</span> <span class="n">type</span> <span class="o" style="color: rgb(249, 38, 114);">:</span> <span class="n">pType</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getActualTypeArguments</span><span class="o" style="color: rgb(249, 38, 114);">())</span> <span class="o" style="color: rgb(249, 38, 114);">{</span>
<span class="n">System</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">out</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">println</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">type</span><span class="o" style="color: rgb(249, 38, 114);">);</span> <span class="c1" style="color: rgb(117, 113, 94);">// 打印两遍: class java.lang.String</span>
<span class="o" style="color: rgb(249, 38, 114);">}</span>
<span class="n">System</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">out</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">println</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">pType</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getOwnerType</span><span class="o" style="color: rgb(249, 38, 114);">());</span> <span class="c1" style="color: rgb(117, 113, 94);">// null</span>
<span class="o" style="color: rgb(249, 38, 114);">}</span>
<span class="o" style="color: rgb(249, 38, 114);">}</span>
</code>
TypeVariable
类型变量, 范型信息在编译时会被转换为一个特定的类型, 而TypeVariable
就是用来反映在JVM编译该泛型前的信息.
它的声明是这样的: public interface TypeVariable<D extends GenericDeclaration> extends Type
也就是说它跟GenericDeclaration
有一定的联系, 我是这么理解的:
TypeVariable
是指在GenericDeclaration
中声明的<T>、<C extends Collection>
这些东西中的那个变量T、C
; 它有如下方法:
Type[] getBounds()
: 获取类型变量的上边界, 若未明确声明上边界则默认为Object
D getGenericDeclaration()
: 获取声明该类型变量实体String getName()
: 获取在源码中定义时的名字
注意:
- 类型变量在定义的时候只能使用
extends
进行(多)边界限定, 不能用super
; - 为什么边界是一个数组? 因为类型变量可以通过
&
进行多个上边界限定,因此上边界有多个
<code style="font-family: Monaco, "Bitstream Vera Sans Mono", "Lucida Console", Terminal; overflow-x: auto;"><span class="kd" style="color: rgb(102, 217, 239);">public</span> <span class="kd" style="color: rgb(102, 217, 239);">class</span> <span class="nc" style="color: rgb(166, 226, 46);">TestType</span> <span class="o" style="color: rgb(249, 38, 114);"><</span><span class="n">K</span> <span class="kd" style="color: rgb(102, 217, 239);">extends</span> <span class="n">Comparable</span> <span class="o" style="color: rgb(249, 38, 114);">&</span> <span class="n">Serializable</span><span class="o" style="color: rgb(249, 38, 114);">,</span> <span class="n">V</span><span class="o" style="color: rgb(249, 38, 114);">></span> <span class="o" style="color: rgb(249, 38, 114);">{</span>
<span class="n">K</span> <span class="n">key</span><span class="o" style="color: rgb(249, 38, 114);">;</span>
<span class="n">V</span> <span class="n">value</span><span class="o" style="color: rgb(249, 38, 114);">;</span>
<span class="kd" style="color: rgb(102, 217, 239);">public</span> <span class="kd" style="color: rgb(102, 217, 239);">static</span> <span class="kt" style="color: rgb(102, 217, 239);">void</span> <span class="n">main</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">String</span><span class="o" style="color: rgb(249, 38, 114);">[]</span> <span class="n">args</span><span class="o" style="color: rgb(249, 38, 114);">)</span> <span class="kd" style="color: rgb(102, 217, 239);">throws</span> <span class="n">Exception</span> <span class="o" style="color: rgb(249, 38, 114);">{</span>
<span class="c1" style="color: rgb(117, 113, 94);">// 获取字段的类型</span>
<span class="n">Field</span> <span class="n">fk</span> <span class="o" style="color: rgb(249, 38, 114);">=</span> <span class="n">TestType</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">class</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getDeclaredField</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="s" style="color: rgb(230, 219, 116);">"key"</span><span class="o" style="color: rgb(249, 38, 114);">);</span>
<span class="n">Field</span> <span class="n">fv</span> <span class="o" style="color: rgb(249, 38, 114);">=</span> <span class="n">TestType</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">class</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getDeclaredField</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="s" style="color: rgb(230, 219, 116);">"value"</span><span class="o" style="color: rgb(249, 38, 114);">);</span>
<span class="n">Assert</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">that</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">fk</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getGenericType</span><span class="o" style="color: rgb(249, 38, 114);">()</span> <span class="k" style="color: rgb(102, 217, 239);">instanceof</span> <span class="n">TypeVariable</span><span class="o" style="color: rgb(249, 38, 114);">,</span> <span class="s" style="color: rgb(230, 219, 116);">"必须为TypeVariable类型"</span><span class="o" style="color: rgb(249, 38, 114);">);</span>
<span class="n">Assert</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">that</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">fv</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getGenericType</span><span class="o" style="color: rgb(249, 38, 114);">()</span> <span class="k" style="color: rgb(102, 217, 239);">instanceof</span> <span class="n">TypeVariable</span><span class="o" style="color: rgb(249, 38, 114);">,</span> <span class="s" style="color: rgb(230, 219, 116);">"必须为TypeVariable类型"</span><span class="o" style="color: rgb(249, 38, 114);">);</span>
<span class="n">TypeVariable</span> <span class="n">keyType</span> <span class="o" style="color: rgb(249, 38, 114);">=</span> <span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">TypeVariable</span><span class="o" style="color: rgb(249, 38, 114);">)</span><span class="n">fk</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getGenericType</span><span class="o" style="color: rgb(249, 38, 114);">();</span>
<span class="n">TypeVariable</span> <span class="n">valueType</span> <span class="o" style="color: rgb(249, 38, 114);">=</span> <span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">TypeVariable</span><span class="o" style="color: rgb(249, 38, 114);">)</span><span class="n">fv</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getGenericType</span><span class="o" style="color: rgb(249, 38, 114);">();</span>
<span class="c1" style="color: rgb(117, 113, 94);">// getName 方法</span>
<span class="n">System</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">out</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">println</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">keyType</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getName</span><span class="o" style="color: rgb(249, 38, 114);">());</span> <span class="c1" style="color: rgb(117, 113, 94);">// K</span>
<span class="n">System</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">out</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">println</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">valueType</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getName</span><span class="o" style="color: rgb(249, 38, 114);">());</span> <span class="c1" style="color: rgb(117, 113, 94);">// V</span>
<span class="c1" style="color: rgb(117, 113, 94);">// getGenericDeclaration 方法</span>
<span class="n">System</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">out</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">println</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">keyType</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getGenericDeclaration</span><span class="o" style="color: rgb(249, 38, 114);">());</span> <span class="c1" style="color: rgb(117, 113, 94);">// class com.test.TestType</span>
<span class="n">System</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">out</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">println</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">valueType</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getGenericDeclaration</span><span class="o" style="color: rgb(249, 38, 114);">());</span> <span class="c1" style="color: rgb(117, 113, 94);">// class com.test.TestType</span>
<span class="c1" style="color: rgb(117, 113, 94);">// getBounds 方法</span>
<span class="n">System</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">out</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">println</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="s" style="color: rgb(230, 219, 116);">"K 的上界:"</span><span class="o" style="color: rgb(249, 38, 114);">);</span> <span class="c1" style="color: rgb(117, 113, 94);">// 有两个</span>
<span class="k" style="color: rgb(102, 217, 239);">for</span> <span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">Type</span> <span class="n">type</span> <span class="o" style="color: rgb(249, 38, 114);">:</span> <span class="n">keyType</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getBounds</span><span class="o" style="color: rgb(249, 38, 114);">())</span> <span class="o" style="color: rgb(249, 38, 114);">{</span> <span class="c1" style="color: rgb(117, 113, 94);">// interface java.lang.Comparable</span>
<span class="n">System</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">out</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">println</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">type</span><span class="o" style="color: rgb(249, 38, 114);">);</span> <span class="c1" style="color: rgb(117, 113, 94);">// interface java.io.Serializable</span>
<span class="o" style="color: rgb(249, 38, 114);">}</span>
<span class="n">System</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">out</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">println</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="s" style="color: rgb(230, 219, 116);">"V 的上界:"</span><span class="o" style="color: rgb(249, 38, 114);">);</span> <span class="c1" style="color: rgb(117, 113, 94);">// 没明确声明上界的, 默认上界是 Object</span>
<span class="k" style="color: rgb(102, 217, 239);">for</span> <span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">Type</span> <span class="n">type</span> <span class="o" style="color: rgb(249, 38, 114);">:</span> <span class="n">valueType</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getBounds</span><span class="o" style="color: rgb(249, 38, 114);">())</span> <span class="o" style="color: rgb(249, 38, 114);">{</span> <span class="c1" style="color: rgb(117, 113, 94);">// class java.lang.Object</span>
<span class="n">System</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">out</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">println</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">type</span><span class="o" style="color: rgb(249, 38, 114);">);</span>
<span class="o" style="color: rgb(249, 38, 114);">}</span>
<span class="o" style="color: rgb(249, 38, 114);">}</span>
<span class="o" style="color: rgb(249, 38, 114);">}</span>
</code>
GenericArrayType
范型数组,组成数组的元素中有范型则实现了该接口; 它的组成元素是ParameterizedType
或TypeVariable
类型,它只有一个方法:
Type getGenericComponentType()
: 返回数组的组成对象, 即被JVM编译后实际的对象
<code style="font-family: Monaco, "Bitstream Vera Sans Mono", "Lucida Console", Terminal; overflow-x: auto;"><span class="kd" style="color: rgb(102, 217, 239);">public</span> <span class="kd" style="color: rgb(102, 217, 239);">class</span> <span class="nc" style="color: rgb(166, 226, 46);">TestType</span> <span class="o" style="color: rgb(249, 38, 114);"><</span><span class="n">T</span><span class="o" style="color: rgb(249, 38, 114);">></span> <span class="o" style="color: rgb(249, 38, 114);">{</span>
<span class="kd" style="color: rgb(102, 217, 239);">public</span> <span class="kd" style="color: rgb(102, 217, 239);">static</span> <span class="kt" style="color: rgb(102, 217, 239);">void</span> <span class="n">main</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">String</span><span class="o" style="color: rgb(249, 38, 114);">[]</span> <span class="n">args</span><span class="o" style="color: rgb(249, 38, 114);">)</span> <span class="kd" style="color: rgb(102, 217, 239);">throws</span> <span class="n">Exception</span> <span class="o" style="color: rgb(249, 38, 114);">{</span>
<span class="n">Method</span> <span class="n">method</span> <span class="o" style="color: rgb(249, 38, 114);">=</span> <span class="n">Test</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">class</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getDeclaredMethods</span><span class="o" style="color: rgb(249, 38, 114);">()[</span><span class="mi" style="color: rgb(174, 129, 255);">0</span><span class="o" style="color: rgb(249, 38, 114);">];</span>
<span class="c1" style="color: rgb(117, 113, 94);">// public void com.test.Test.show(java.util.List[],java.lang.Object[],java.util.List,java.lang.String[],int[])</span>
<span class="n">System</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">out</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">println</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">method</span><span class="o" style="color: rgb(249, 38, 114);">);</span>
<span class="n">Type</span><span class="o" style="color: rgb(249, 38, 114);">[]</span> <span class="n">types</span> <span class="o" style="color: rgb(249, 38, 114);">=</span> <span class="n">method</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getGenericParameterTypes</span><span class="o" style="color: rgb(249, 38, 114);">();</span> <span class="c1" style="color: rgb(117, 113, 94);">// 这是 Method 中的方法</span>
<span class="k" style="color: rgb(102, 217, 239);">for</span> <span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">Type</span> <span class="n">type</span> <span class="o" style="color: rgb(249, 38, 114);">:</span> <span class="n">types</span><span class="o" style="color: rgb(249, 38, 114);">)</span> <span class="o" style="color: rgb(249, 38, 114);">{</span>
<span class="n">System</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">out</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">println</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">type</span> <span class="k" style="color: rgb(102, 217, 239);">instanceof</span> <span class="n">GenericArrayType</span><span class="o" style="color: rgb(249, 38, 114);">);</span>
<span class="o" style="color: rgb(249, 38, 114);">}</span>
<span class="o" style="color: rgb(249, 38, 114);">}</span>
<span class="o" style="color: rgb(249, 38, 114);">}</span>
<span class="kd" style="color: rgb(102, 217, 239);">class</span> <span class="nc" style="color: rgb(166, 226, 46);">Test</span><span class="o" style="color: rgb(249, 38, 114);"><</span><span class="n">T</span><span class="o" style="color: rgb(249, 38, 114);">></span> <span class="o" style="color: rgb(249, 38, 114);">{</span>
<span class="kd" style="color: rgb(102, 217, 239);">public</span> <span class="kt" style="color: rgb(102, 217, 239);">void</span> <span class="n">show</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">List</span><span class="o" style="color: rgb(249, 38, 114);"><</span><span class="n">String</span><span class="o" style="color: rgb(249, 38, 114);">>[]</span> <span class="n">pTypeArray</span><span class="o" style="color: rgb(249, 38, 114);">,</span> <span class="n">T</span><span class="o" style="color: rgb(249, 38, 114);">[]</span> <span class="n">vTypeArray</span><span class="o" style="color: rgb(249, 38, 114);">,</span> <span class="n">List</span><span class="o" style="color: rgb(249, 38, 114);"><</span><span class="n">String</span><span class="o" style="color: rgb(249, 38, 114);">></span> <span class="n">list</span><span class="o" style="color: rgb(249, 38, 114);">,</span> <span class="n">String</span><span class="o" style="color: rgb(249, 38, 114);">[]</span> <span class="n">strings</span><span class="o" style="color: rgb(249, 38, 114);">,</span> <span class="kt" style="color: rgb(102, 217, 239);">int</span><span class="o" style="color: rgb(249, 38, 114);">[]</span> <span class="n">ints</span><span class="o" style="color: rgb(249, 38, 114);">)</span> <span class="o" style="color: rgb(249, 38, 114);">{</span>
<span class="o" style="color: rgb(249, 38, 114);">}</span>
<span class="o" style="color: rgb(249, 38, 114);">}</span>
</code>
- 第一个参数
List<String>[]
的组成元素List<String>
是ParameterizedType
类型, 打印结果为true
- 第二个参数
T[]
的组成元素T
是TypeVariable
类型, 打印结果为true
- 第三个参数
List<String>
不是数组, 打印结果为false
- 第四个参数
String[]
的组成元素String
是普通对象, 没有范型, 打印结果为false
- 第五个参数
int[] pTypeArray
的组成元素int
是原生类型, 也没有范型, 打印结果为false
WildcardType
该接口表示通配符泛型, 比如? extends Number
和 ? super Integer
它有如下方法:
Type[] getUpperBounds()
: 获取范型变量的上界Type[] getLowerBounds()
: 获取范型变量的下界
注意:
- 现阶段通配符只接受一个上边界或下边界, 返回数组是为了以后的扩展, 实际上现在返回的数组的大小是1
<code style="font-family: Monaco, "Bitstream Vera Sans Mono", "Lucida Console", Terminal; overflow-x: auto;"><span class="kd" style="color: rgb(102, 217, 239);">public</span> <span class="kd" style="color: rgb(102, 217, 239);">class</span> <span class="nc" style="color: rgb(166, 226, 46);">TestType</span> <span class="o" style="color: rgb(249, 38, 114);">{</span>
<span class="kd" style="color: rgb(102, 217, 239);">private</span> <span class="n">List</span><span class="o" style="color: rgb(249, 38, 114);"><?</span> <span class="kd" style="color: rgb(102, 217, 239);">extends</span> <span class="n">Number</span><span class="o" style="color: rgb(249, 38, 114);">></span> <span class="n">a</span><span class="o" style="color: rgb(249, 38, 114);">;</span> <span class="c1" style="color: rgb(117, 113, 94);">// // a没有下界, 取下界会抛出ArrayIndexOutOfBoundsException</span>
<span class="kd" style="color: rgb(102, 217, 239);">private</span> <span class="n">List</span><span class="o" style="color: rgb(249, 38, 114);"><?</span> <span class="kd" style="color: rgb(102, 217, 239);">super</span> <span class="n">String</span><span class="o" style="color: rgb(249, 38, 114);">></span> <span class="n">b</span><span class="o" style="color: rgb(249, 38, 114);">;</span>
<span class="kd" style="color: rgb(102, 217, 239);">public</span> <span class="kd" style="color: rgb(102, 217, 239);">static</span> <span class="kt" style="color: rgb(102, 217, 239);">void</span> <span class="n">main</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">String</span><span class="o" style="color: rgb(249, 38, 114);">[]</span> <span class="n">args</span><span class="o" style="color: rgb(249, 38, 114);">)</span> <span class="kd" style="color: rgb(102, 217, 239);">throws</span> <span class="n">Exception</span> <span class="o" style="color: rgb(249, 38, 114);">{</span>
<span class="n">Field</span> <span class="n">fieldA</span> <span class="o" style="color: rgb(249, 38, 114);">=</span> <span class="n">TestType</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">class</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getDeclaredField</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="s" style="color: rgb(230, 219, 116);">"a"</span><span class="o" style="color: rgb(249, 38, 114);">);</span>
<span class="n">Field</span> <span class="n">fieldB</span> <span class="o" style="color: rgb(249, 38, 114);">=</span> <span class="n">TestType</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">class</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getDeclaredField</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="s" style="color: rgb(230, 219, 116);">"b"</span><span class="o" style="color: rgb(249, 38, 114);">);</span>
<span class="c1" style="color: rgb(117, 113, 94);">// 先拿到范型类型</span>
<span class="n">Assert</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">that</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">fieldA</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getGenericType</span><span class="o" style="color: rgb(249, 38, 114);">()</span> <span class="k" style="color: rgb(102, 217, 239);">instanceof</span> <span class="n">ParameterizedType</span><span class="o" style="color: rgb(249, 38, 114);">,</span> <span class="s" style="color: rgb(230, 219, 116);">""</span><span class="o" style="color: rgb(249, 38, 114);">);</span>
<span class="n">Assert</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">that</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">fieldB</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getGenericType</span><span class="o" style="color: rgb(249, 38, 114);">()</span> <span class="k" style="color: rgb(102, 217, 239);">instanceof</span> <span class="n">ParameterizedType</span><span class="o" style="color: rgb(249, 38, 114);">,</span> <span class="s" style="color: rgb(230, 219, 116);">""</span><span class="o" style="color: rgb(249, 38, 114);">);</span>
<span class="n">ParameterizedType</span> <span class="n">pTypeA</span> <span class="o" style="color: rgb(249, 38, 114);">=</span> <span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">ParameterizedType</span><span class="o" style="color: rgb(249, 38, 114);">)</span> <span class="n">fieldA</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getGenericType</span><span class="o" style="color: rgb(249, 38, 114);">();</span>
<span class="n">ParameterizedType</span> <span class="n">pTypeB</span> <span class="o" style="color: rgb(249, 38, 114);">=</span> <span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">ParameterizedType</span><span class="o" style="color: rgb(249, 38, 114);">)</span> <span class="n">fieldB</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getGenericType</span><span class="o" style="color: rgb(249, 38, 114);">();</span>
<span class="c1" style="color: rgb(117, 113, 94);">// 再从范型里拿到通配符类型</span>
<span class="n">Assert</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">that</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">pTypeA</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getActualTypeArguments</span><span class="o" style="color: rgb(249, 38, 114);">()[</span><span class="mi" style="color: rgb(174, 129, 255);">0</span><span class="o" style="color: rgb(249, 38, 114);">]</span> <span class="k" style="color: rgb(102, 217, 239);">instanceof</span> <span class="n">WildcardType</span><span class="o" style="color: rgb(249, 38, 114);">,</span> <span class="s" style="color: rgb(230, 219, 116);">""</span><span class="o" style="color: rgb(249, 38, 114);">);</span>
<span class="n">Assert</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">that</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">pTypeB</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getActualTypeArguments</span><span class="o" style="color: rgb(249, 38, 114);">()[</span><span class="mi" style="color: rgb(174, 129, 255);">0</span><span class="o" style="color: rgb(249, 38, 114);">]</span> <span class="k" style="color: rgb(102, 217, 239);">instanceof</span> <span class="n">WildcardType</span><span class="o" style="color: rgb(249, 38, 114);">,</span> <span class="s" style="color: rgb(230, 219, 116);">""</span><span class="o" style="color: rgb(249, 38, 114);">);</span>
<span class="n">WildcardType</span> <span class="n">wTypeA</span> <span class="o" style="color: rgb(249, 38, 114);">=</span> <span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">WildcardType</span><span class="o" style="color: rgb(249, 38, 114);">)</span> <span class="n">pTypeA</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getActualTypeArguments</span><span class="o" style="color: rgb(249, 38, 114);">()[</span><span class="mi" style="color: rgb(174, 129, 255);">0</span><span class="o" style="color: rgb(249, 38, 114);">];</span>
<span class="n">WildcardType</span> <span class="n">wTypeB</span> <span class="o" style="color: rgb(249, 38, 114);">=</span> <span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">WildcardType</span><span class="o" style="color: rgb(249, 38, 114);">)</span> <span class="n">pTypeB</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getActualTypeArguments</span><span class="o" style="color: rgb(249, 38, 114);">()[</span><span class="mi" style="color: rgb(174, 129, 255);">0</span><span class="o" style="color: rgb(249, 38, 114);">];</span>
<span class="c1" style="color: rgb(117, 113, 94);">// 方法测试</span>
<span class="n">System</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">out</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">println</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">wTypeA</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getUpperBounds</span><span class="o" style="color: rgb(249, 38, 114);">()[</span><span class="mi" style="color: rgb(174, 129, 255);">0</span><span class="o" style="color: rgb(249, 38, 114);">]);</span> <span class="c1" style="color: rgb(117, 113, 94);">// class java.lang.Number</span>
<span class="n">System</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">out</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">println</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">wTypeB</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getLowerBounds</span><span class="o" style="color: rgb(249, 38, 114);">()[</span><span class="mi" style="color: rgb(174, 129, 255);">0</span><span class="o" style="color: rgb(249, 38, 114);">]);</span> <span class="c1" style="color: rgb(117, 113, 94);">// class java.lang.String</span>
<span class="c1" style="color: rgb(117, 113, 94);">// 看看通配符类型到底是什么, 打印结果为: ? extends java.lang.Number</span>
<span class="n">System</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">out</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">println</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">wTypeA</span><span class="o" style="color: rgb(249, 38, 114);">);</span>
<span class="o" style="color: rgb(249, 38, 114);">}</span>
<span class="o" style="color: rgb(249, 38, 114);">}</span>
</code>
再写几个边界的例子:
List<? extends Number>
, 上界为class java.lang.Number
, 属于Class
类型List<? extends List<T>>
, 上界为java.util.List<T>
, 属于ParameterizedType
类型List<? extends List<String>>
, 上界为java.util.List<java.lang.String>
, 属于ParameterizedType
类型List<? extends T>
, 上界为T
, 属于TypeVariable
类型List<? extends T[]>
, 上界为T[]
, 属于GenericArrayType
类型
它们最终统一成Type作为数组的元素类型
Type及其子接口的来历
泛型出现之前的类型
没有泛型的时候,只有原始类型。此时,所有的原始类型都通过字节码文件类Class类进行抽象。Class类的一个具体对象就代表一个指定的原始类型。
泛型出现之后的类型
泛型出现之后,扩充了数据类型。从只有原始类型扩充了参数化类型、类型变量类型、限定符类型 、泛型数组类型。
与泛型有关的类型不能和原始类型统一到Class的原因
- 产生泛型擦除的原因
原始类型和新产生的类型都应该统一成各自的字节码文件类型对象。但是由于泛型不是最初Java中的成分。如果真的加入了泛型,涉及到JVM指令集的修改,这是非常致命的。
- Java中如何引入泛型
为了使用泛型又不真正引入泛型,Java采用泛型擦除机制来引入泛型。Java中的泛型仅仅是给编译器javac使用的,确保数据的安全性和免去强制类型转换的麻烦。但是,一旦编译完成,所有的和泛型有关的类型全部擦除。
- Class不能表达与泛型有关的类型
因此,与泛型有关的参数化类型、类型变量类型、限定符类型 、泛型数组类型这些类型编译后全部被打回原形,在字节码文件中全部都是泛型被擦除后的原始类型,并不存在和自身类型对应的字节码文件。所以和泛型相关的新扩充进来的类型不能被统一到Class类中。
- 与泛型有关的类型在Java中的表示
为了通过反射操作这些类型以迎合实际开发的需要,Java就新增了ParameterizedType, TypeVariable<D>, GenericArrayType, WildcardType
几种类型来代表不能被归一到Class类中的类型但是又和原始类型齐名的类型。
- 引入Type的原因
为了程序的扩展性,最终引入了Type接口作为Class和ParameterizedType, TypeVariable<D>, GenericArrayType, WildcardType
这几种类型的总的父接口。这样可以用Type类型的参数来接受以上五种子类的实参或者返回值类型就是Type类型的参数。统一了与泛型有关的类型和原始类型Class
- Type接口中没有方法的原因
从上面看到,Type的出现仅仅起到了通过多态来达到程序扩展性提高的作用,没有其他的作用。因此Type接口的源码中没有任何方法。
Class类简介
Class类位于java.lang
包中, Class类的实例表示正在运行的Java应用程序中的类和接口.
枚举算类, 注解算接口; 数组算类,它映射的Class对象被有着相同元素和大小的数组共享;
Java的原生(primitive types)类型(boolean、byte、char、short、int、long、float、double
)和关键字void
也代表Class对象.
Class类实现了Serializable、GenericDeclaration、Type、AnnotatedElement
接口
Class类无public构造函数, Class类对象是由JVM在类加载的时候调用类加载器的defineClass
方法创建的.
如下方法能够获取类名:
obj.getClass().getName()
Foo.class.getName()
判定方法
这些方法可以判断某个类是否是接口、是否是枚举、是否是注解、是否有某个注解、是否是匿名类、是否是某个类的超类(是否可强制转换为该类)等
boolean isArray()
: 是否是数组;int[].class.isArray()
为true
boolean isAnnotation()
: 是否是注解, 若返回true
,则isInterface
也为ture
;Target.class.isAnnotation()
为true
boolean isEnum()
: 是否是枚举类boolean isPrimitive()
: 是否是原生类型(共9个, 包装类返回false
),void.class.isArray()
为true
boolean isInterface()
: 是否是接口boolean isMemberClass()
: 是否是成员类, 类的定义在另一个类里面的那种boolean isAnonymousClass()
: 是否是匿名类boolean isLocalClass()
: 是否是本地类boolean isSynthetic()
: 是否是复合类 (接口Member
也有这个方法)boolean isInstance(Object obj)
: obj是否是该类的一个实例boolean isAssignableFrom(Class<?> cls)
: cls是否可以被转换成该类boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)
: 该类上是否存在这个注解(继承自接口AnnotatedElement
)
下面是几个方法的实例说明:
<code style="font-family: Monaco, "Bitstream Vera Sans Mono", "Lucida Console", Terminal; overflow-x: auto;"><span class="kd" style="color: rgb(102, 217, 239);">public</span> <span class="kd" style="color: rgb(102, 217, 239);">class</span> <span class="nc" style="color: rgb(166, 226, 46);">Main</span> <span class="o" style="color: rgb(249, 38, 114);">{</span>
<span class="kd" style="color: rgb(102, 217, 239);">class</span> <span class="nc" style="color: rgb(166, 226, 46);">Test</span><span class="o" style="color: rgb(249, 38, 114);">{}</span> <span class="c1" style="color: rgb(117, 113, 94);">// 这是传说中的成员类</span>
<span class="kd" style="color: rgb(102, 217, 239);">public</span> <span class="kd" style="color: rgb(102, 217, 239);">static</span> <span class="kt" style="color: rgb(102, 217, 239);">void</span> <span class="n">main</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">String</span><span class="o" style="color: rgb(249, 38, 114);">[]</span> <span class="n">args</span><span class="o" style="color: rgb(249, 38, 114);">)</span> <span class="o" style="color: rgb(249, 38, 114);">{</span>
<span class="kd" style="color: rgb(102, 217, 239);">class</span> <span class="nc" style="color: rgb(166, 226, 46);">LocalClass</span><span class="o" style="color: rgb(249, 38, 114);">{}</span> <span class="c1" style="color: rgb(117, 113, 94);">// 这是传说中的本地类</span>
<span class="n">Object</span> <span class="n">obj</span> <span class="o" style="color: rgb(249, 38, 114);">=</span> <span class="k" style="color: rgb(102, 217, 239);">new</span> <span class="n">Hello</span><span class="o" style="color: rgb(249, 38, 114);">(){</span> <span class="c1" style="color: rgb(117, 113, 94);">// Hello是其他地方定义的一个接口, 有一个sayHello()方法, 这就是匿名类(无类名)</span>
<span class="kd" style="color: rgb(102, 217, 239);">public</span> <span class="kt" style="color: rgb(102, 217, 239);">void</span> <span class="n">sayHello</span><span class="o" style="color: rgb(249, 38, 114);">()</span> <span class="o" style="color: rgb(249, 38, 114);">{</span>
<span class="o" style="color: rgb(249, 38, 114);">}</span>
<span class="o" style="color: rgb(249, 38, 114);">};</span>
<span class="n">System</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">out</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">println</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">Test</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">class</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">isMemberClass</span><span class="o" style="color: rgb(249, 38, 114);">());</span> <span class="c1" style="color: rgb(117, 113, 94);">// true</span>
<span class="n">System</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">out</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">println</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">obj</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getClass</span><span class="o" style="color: rgb(249, 38, 114);">().</span><span class="na" style="color: rgb(166, 226, 46);">isAnonymousClass</span><span class="o" style="color: rgb(249, 38, 114);">());</span> <span class="c1" style="color: rgb(117, 113, 94);">// true</span>
<span class="n">System</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">out</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">println</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">LocalClass</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">class</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">isLocalClass</span><span class="o" style="color: rgb(249, 38, 114);">());</span> <span class="c1" style="color: rgb(117, 113, 94);">// true</span>
<span class="n">System</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">out</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">println</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">Hello</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">class</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">isInstance</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">obj</span><span class="o" style="color: rgb(249, 38, 114);">));</span> <span class="c1" style="color: rgb(117, 113, 94);">// true</span>
<span class="n">System</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">out</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">println</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">Bean</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">class</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">isAnnotationPresent</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">Target</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">class</span><span class="o" style="color: rgb(249, 38, 114);">));</span> <span class="c1" style="color: rgb(117, 113, 94);">// true</span>
<span class="o" style="color: rgb(249, 38, 114);">}</span>
<span class="o" style="color: rgb(249, 38, 114);">}</span>
</code>
instanceof
、isInstance
、isAssignableFrom
的区别
instanceof
运算符只被用于对象引用变量, 比如: 自身类或子类的实例 instanceof 自身类
返回true
isInstance(Object obj)
是instanceof
运算符的动态等价, 比如: 自身类.class.isInstance(自身类或子类的实例)
返回true
isAssignableFrom(Class<?> cls)
是两个类之间的关系, 比如: 自身类.class.isAssignableFrom(自身类或子类.class)
返回true
获取内容系列方法
通过Class类可以获取这个类的一些内容性质的信息, 比如属性、方法、构造方法、注解
获取属性
Field[] getFields()
: 获取本类或父类中所有public属性Field getField(String name)
: 获取本类或父类中特定名字的public属性Field[] getDeclaredFields()
: 获取本类中声明的所有属性Field getDeclaredField(String name)
: 获取本类中声明的特定名字的属性
获取方法
Method[] getMethods()
: 获取本类或父类中所有public方法(包括构造器方法)Method getMethod(String name, Class<?>... parameterTypes)
: 获取本类或父类中特定名字和参数的public方法Method[] getDeclaredMethods()
: 获取本类中声明的所有方法(包括非public但不包括继承来的)Method getDeclaredMethod(String name, Class<?>... parameterTypes)
: 获取本类中声明的特定名字和参数的方法(最常用)
获取构造方法
Constructor<?>[] getConstructors()
: 获取本类中所有public构造器Constructor<T> getConstructor(Class<?>... parameterTypes)
: 获取本类中特定参数的public构造器Constructor<?>[] getDeclaredConstructors()
: 获取本类中所有构造器Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
: 获取本类中指定参数的构造器
获取注解
这几个方法均继承自接口AnnotatedElement
Annotation[] getAnnotations()
: 获取这个元素上的所有注解(包括父类上被@Inherited
标记的注解)<A extends Annotation> A getAnnotation(Class<A> annotationClass)
: 获取这个元素上指定类型的注解, 没有返回nullAnnotation[] getDeclaredAnnotations()
: 获取直接标注在这个元素上的注解
父类子类(接口)相关
Class<? super T> getSuperclass()
: 返回本类的父类(直接超类);int[].class
为Object
,int.class
为null
,Object.class
为null
Type getGenericSuperclass()
: 以Type的形式返回本类的父类, 带有范型信息(没有范型信息时把Class以Type形式返回)Class<?>[] getInterfaces()
: 返回本类直接实现的接口Type[] getGenericInterfaces()
: 以Type的形式返回本类直接实现的接口, 带有范型信息<U> Class<? extends U> asSubclass(Class<U> clazz)
: 把当前类转为clazz表示的子类(或自己), 不能转抛ClassCastException
异常
asSubclass
的作用
ArrayList.class.asSubclass(List.class)
得到的还是ArrayList.class
, 看起来没什么作用
但是它的作用体现在窄化未知的Class类型的范围, 比如通常我们用到Class.forName("XXX")
, 它的返回是Class<?>
比较宽泛, 我们可以窄化一下:Class.forName("XXX").asSubclass(List.class).newInstance()
. 当XXX
不是List
的子类时,抛出ClassCastException
异常
内部类相关
Class<?> getEnclosingClass()
: 获取底层类的直接封闭类, 如上面LocalClass
的封闭类为Main
, 那个匿名类的封闭类也是Main
Constructor<?> getEnclosingConstructor()
: 若该Class对象是在一个构造方法中的本地类或匿名类时, 返回这个构造器对象, 表示底层类直接封闭构造方法, 否则返回null
; 上面的LocalClass
不在构造方法中,因此返回null
Method getEnclosingMethod()
: 若该Class对象是在一个方法中的本地类或匿名类时, 返回这个Method
对象, 表示底层类的直接封闭方法, 否则返回null
Class<?> getDeclaringClass()
: 该类是另一个类的成员(isMemberClass
),则返回该类的声明类(外部类); 接口Member
中也有该方法Class<?>[] getDeclaredClasses()
: 返回该类中直接声明的所有类Class<?>[] getClasses()
: 返回该类中直接声明的所有public类
名字相关
static Class<?> forName(String className)
: 返回与给定的字符串名称相关联的Class对象String getSimpleName()
: 返回源码中定义的简单类名, 匿名类返回空串, 数组返回”组件类型[]”String getCanonicalName
: 返回底层类的Java语言规范中定义的标准名称public String getName()
: 返回此Class对象所表示的实体(类,接口,数组类,基本类型或void)的名字, 略复杂,规则如下:- 若是原始类型(class), 则返回Java语言规范中定义的标准名称
- 若是原生类型(primitive)或void, 直接返回关键字对应的字符串
- 若是数组, 则用”[“代表数组维度,后面跟上元素类型代码,具体如下表:
元素类型 | 类型代码 |
---|---|
boolean | Z |
byte | B |
char | C |
double | D |
float | F |
int | I |
long | J |
short | S |
class or interface | Lclassname; |
来个例子:
<code style="font-family: Monaco, "Bitstream Vera Sans Mono", "Lucida Console", Terminal; overflow-x: auto;"><span class="kd" style="color: rgb(102, 217, 239);">public</span> <span class="kd" style="color: rgb(102, 217, 239);">class</span> <span class="nc" style="color: rgb(166, 226, 46);">ClassTest</span> <span class="o" style="color: rgb(249, 38, 114);">{</span>
<span class="kd" style="color: rgb(102, 217, 239);">public</span> <span class="kd" style="color: rgb(102, 217, 239);">static</span> <span class="kt" style="color: rgb(102, 217, 239);">void</span> <span class="n">main</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">String</span><span class="o" style="color: rgb(249, 38, 114);">[]</span> <span class="n">args</span><span class="o" style="color: rgb(249, 38, 114);">)</span> <span class="kd" style="color: rgb(102, 217, 239);">throws</span> <span class="n">Exception</span> <span class="o" style="color: rgb(249, 38, 114);">{</span>
<span class="n">Class</span> <span class="n">clazz</span> <span class="o" style="color: rgb(249, 38, 114);">=</span> <span class="n">String</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">class</span><span class="o" style="color: rgb(249, 38, 114);">;</span>
<span class="n">System</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">out</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">println</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">clazz</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getSimpleName</span><span class="o" style="color: rgb(249, 38, 114);">());</span> <span class="c1" style="color: rgb(117, 113, 94);">// String</span>
<span class="n">System</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">out</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">println</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">clazz</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getCanonicalName</span><span class="o" style="color: rgb(249, 38, 114);">());</span> <span class="c1" style="color: rgb(117, 113, 94);">// java.lang.String</span>
<span class="n">System</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">out</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">println</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">clazz</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getName</span><span class="o" style="color: rgb(249, 38, 114);">());</span> <span class="c1" style="color: rgb(117, 113, 94);">// java.lang.String</span>
<span class="n">clazz</span> <span class="o" style="color: rgb(249, 38, 114);">=</span> <span class="kt" style="color: rgb(102, 217, 239);">int</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">class</span><span class="o" style="color: rgb(249, 38, 114);">;</span>
<span class="n">System</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">out</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">println</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">clazz</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getSimpleName</span><span class="o" style="color: rgb(249, 38, 114);">());</span> <span class="c1" style="color: rgb(117, 113, 94);">// int</span>
<span class="n">System</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">out</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">println</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">clazz</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getCanonicalName</span><span class="o" style="color: rgb(249, 38, 114);">());</span> <span class="c1" style="color: rgb(117, 113, 94);">// int</span>
<span class="n">System</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">out</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">println</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">clazz</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getName</span><span class="o" style="color: rgb(249, 38, 114);">());</span> <span class="c1" style="color: rgb(117, 113, 94);">// int</span>
<span class="n">String</span><span class="o" style="color: rgb(249, 38, 114);">[]</span> <span class="n">strings</span> <span class="o" style="color: rgb(249, 38, 114);">=</span> <span class="o" style="color: rgb(249, 38, 114);">{</span><span class="s" style="color: rgb(230, 219, 116);">"a"</span><span class="o" style="color: rgb(249, 38, 114);">,</span> <span class="s" style="color: rgb(230, 219, 116);">"b"</span><span class="o" style="color: rgb(249, 38, 114);">};</span>
<span class="n">clazz</span> <span class="o" style="color: rgb(249, 38, 114);">=</span> <span class="n">strings</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getClass</span><span class="o" style="color: rgb(249, 38, 114);">();</span>
<span class="n">System</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">out</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">println</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">clazz</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getSimpleName</span><span class="o" style="color: rgb(249, 38, 114);">());</span> <span class="c1" style="color: rgb(117, 113, 94);">// String[]</span>
<span class="n">System</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">out</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">println</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">clazz</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getCanonicalName</span><span class="o" style="color: rgb(249, 38, 114);">());</span> <span class="c1" style="color: rgb(117, 113, 94);">// java.lang.String[]</span>
<span class="n">System</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">out</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">println</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">clazz</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getName</span><span class="o" style="color: rgb(249, 38, 114);">());</span> <span class="c1" style="color: rgb(117, 113, 94);">// [Ljava.lang.String;</span>
<span class="kt" style="color: rgb(102, 217, 239);">int</span><span class="o" style="color: rgb(249, 38, 114);">[][]</span> <span class="n">array</span> <span class="o" style="color: rgb(249, 38, 114);">=</span> <span class="o" style="color: rgb(249, 38, 114);">{</span><span class="k" style="color: rgb(102, 217, 239);">new</span> <span class="kt" style="color: rgb(102, 217, 239);">int</span><span class="o" style="color: rgb(249, 38, 114);">[]{</span><span class="mi" style="color: rgb(174, 129, 255);">1</span><span class="o" style="color: rgb(249, 38, 114);">,</span> <span class="mi" style="color: rgb(174, 129, 255);">2</span><span class="o" style="color: rgb(249, 38, 114);">},</span> <span class="k" style="color: rgb(102, 217, 239);">new</span> <span class="kt" style="color: rgb(102, 217, 239);">int</span><span class="o" style="color: rgb(249, 38, 114);">[]{</span><span class="mi" style="color: rgb(174, 129, 255);">10</span><span class="o" style="color: rgb(249, 38, 114);">,</span> <span class="mi" style="color: rgb(174, 129, 255);">20</span><span class="o" style="color: rgb(249, 38, 114);">}};</span>
<span class="n">clazz</span> <span class="o" style="color: rgb(249, 38, 114);">=</span> <span class="n">array</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getClass</span><span class="o" style="color: rgb(249, 38, 114);">();</span>
<span class="n">System</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">out</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">println</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">clazz</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getSimpleName</span><span class="o" style="color: rgb(249, 38, 114);">());</span> <span class="c1" style="color: rgb(117, 113, 94);">// int[][]</span>
<span class="n">System</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">out</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">println</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">clazz</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getCanonicalName</span><span class="o" style="color: rgb(249, 38, 114);">());</span> <span class="c1" style="color: rgb(117, 113, 94);">// int[][]</span>
<span class="n">System</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">out</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">println</span><span class="o" style="color: rgb(249, 38, 114);">(</span><span class="n">clazz</span><span class="o" style="color: rgb(249, 38, 114);">.</span><span class="na" style="color: rgb(166, 226, 46);">getName</span><span class="o" style="color: rgb(249, 38, 114);">());</span> <span class="c1" style="color: rgb(117, 113, 94);">// [[I</span>
<span class="o" style="color: rgb(249, 38, 114);">}</span>
<span class="o" style="color: rgb(249, 38, 114);">}</span>
</code>
其他方法
TypeVariable<Class<T>>[] getTypeParameters()
: 继承自接口GenericDeclaration
,按照声明顺序返回声明的类型变量Class<?> getComponentType()
: 若该类是个数组,则返回组件的类型
还有一些方法暂不介绍了.