Java之reflection(反射机制)——通过反射操作泛型,注解
一、反射操作泛型(Generic)
Java采用泛型擦除机制来引入泛型。Java中的泛型仅仅是给编译器Javac使用的,确保数据的安全性和免去强制类型转换的麻烦。但是编译一旦完成,所有和泛型有关的类型全部被擦除。
为了通过反射操作这些类型以迎合实际开发的需要,Java新增了ParameterizedType,GenericArrayType,TypeVariable和WildcardType几种类型来代表不能被归一到Class类中的类型但是又和原始类型齐名的类型。
- ParameterizedType:表示一种参数化的类型,比如Collection< String >
- GenericArrayType:表示一种元素类型是参数化类型或者类型变量的数组类型
- TypeVariable:是各种类型变量的公共父接口
WildcardType:代表一种通配符类型表达式,比如?、? extends Number、? super Integer。(wildcard是一个单词:就是”通配符“)
代码示例:
package reflection; import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map; /**
* 通过反射获取泛型信息
*
*/
public class Demo{
//定义两个带泛型的方法
public void test01(Map<String,Person> map,List<Person> list){
System.out.println("Demo.test01()");
}
public Map<Integer,Person> test02(){
System.out.println("Demo.test02()");
return null;
} public static void main(String[] args) {
try {
//获得指定方法参数泛型信息
Method m = Demo.class.getMethod("test01", Map.class,List.class);
Type[] t = m.getGenericParameterTypes(); for (Type paramType : t) {
System.out.println("#"+paramType);
if(paramType instanceof ParameterizedType){
//获取泛型中的具体信息
Type[] genericTypes = ((ParameterizedType) paramType).getActualTypeArguments();
for (Type genericType : genericTypes) {
System.out.println("泛型类型:"+genericType);
}
}
} //获得指定方法返回值泛型信息
Method m2 = Demo.class.getMethod("test02", null);
Type returnType = m2.getGenericReturnType();
if(returnType instanceof ParameterizedType){
Type[] genericTypes = ((ParameterizedType) returnType).getActualTypeArguments(); for (Type genericType : genericTypes) {
System.out.println("返回值,泛型类型:"+genericType);
}
} } catch (Exception e) {
e.printStackTrace();
}
}
}
输出结果:
#java.util.Map< java.lang.String, reflection.Person >
泛型类型:class java.lang.String
泛型类型:class reflection.Person
#java.util.List< reflection.Person >
泛型类型:class reflection.Person
返回值,泛型类型:class java.lang.Integer
返回值,泛型类型:class reflection.Person
二、反射操作注解(Annotation)
Method/Constructor/Field/Element 都继承了 AccessibleObject , AccessibleObject 类中有一个 setAccessible 方法:
具体使用可以就看我的之前的文章注解处理器
好了,介绍了两个简单的反射的应用,在顺便讲一下Java反射机制的性能问题。
三、反射性能测试
Method/Constructor/Field/Element 都继承了 AccessibleObject , AccessibleObject 类中有一个 setAccessible 方法:
public void setAccessible(booleanflag)throws SecurityException
{
...
}
该方法有两个作用:
- 启用/禁用访问安全检查开关:值为true,则指示反射的对象在使用时取消Java语言访问检查; 值为false,则指示应该实施Java语言的访问检查;
- 可以禁止安全检查, 提高反射的运行效率.
测试代码:
package reflection; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; public class TestReflect {
public static void testNoneReflect() {
Person user = new Person(); long start = System.currentTimeMillis();
for (long i = 0; i < Integer.MAX_VALUE; ++i) {
user.getName();
}
long count = System.currentTimeMillis() - start;
System.out.println("没有反射, 共消耗 <" + count + "> 毫秒");
} public static void testNotAccess() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
Person user = new Person();
Method method = Class.forName("reflection.Person").getMethod("getName"); long start = System.currentTimeMillis();
for (long i = 0; i < Integer.MAX_VALUE; ++i) {
method.invoke(user, null);
}
long count = System.currentTimeMillis() - start;
System.out.println("没有访问权限, 共消耗 <" + count + "> 毫秒");
} public static void testUseAccess() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
Person user = new Person();
Method method = Class.forName("reflection.Person").getMethod("getName");
method.setAccessible(true); long start = System.currentTimeMillis();
for (long i = 0; i < Integer.MAX_VALUE; ++i) {
method.invoke(user, null);
}
long count = System.currentTimeMillis() - start;
System.out.println("有访问权限, 共消耗 <" + count + "> 毫秒");
} public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
testNoneReflect();
testNotAccess();
testUseAccess();
}
}
输出结果:
没有反射, 共消耗 <912> 毫秒
没有访问权限, 共消耗 <4366> 毫秒 有访问权限, 共消耗 <2843> 毫秒
可以看到使用反射会比直接调用慢2000 毫秒 ,但是前提是该方法会执行20E+次(而且服务器的性能也肯定比我的机器要高),因此在我们的实际开发中,其实是不用担心反射机制带来的性能消耗的,而且禁用访问权限检查,也会有性能的提升。
Java之reflection(反射机制)——通过反射操作泛型,注解的更多相关文章
- java学习--Reflection反射机制
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意方法和属性:这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制. ...
- Java进阶之reflection(反射机制)——反射概念与基础
反射机制是Java动态性之一,而说到动态性首先得了解动态语言.那么何为动态语言? 一.动态语言 动态语言,是指程序在运行时可以改变其结构:新的函数可以引进,已有的函数可以被删除等结构上的变化.比如常见 ...
- Java动态性之反射机制(reflection)
说到反射机制,第一次接触的人可能会比较懵,反射?什么反射?怎么反射?反射是干嘛的?下面我将在这篇文章中讲讲Java的反射机制 不过在这之前,还有一个问题需要解决,标题名中的动态性,说起动态性,我先介绍 ...
- Java中的反射机制Reflection
目录 什么是反射? 获取.class字节码文件对象 获取该.class字节码文件对象的详细信息 通过反射机制执行函数 反射链 反射机制是java的一个非常重要的机制,一些著名的应用框架都使用了此机制, ...
- 浅说Java中的反射机制(一)
在学习传智播客李勇老师的JDBC系列时,会出现反射的概念,由于又是第一次见,不免感到陌生.所以再次在博客园找到一篇文章,先记录如下: 引用自java中的反射机制,作者bingoideas.(()为我手 ...
- 深入理解Java中的反射机制
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意方法和属性:这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制. ...
- 黑马程序员——【Java高新技术】——反射机制
---------- android培训.java培训.期待与您交流! ---------- 一.概述 1.Java反射机制:是指“在运行状态中”,对于任意一个类,都能够知道这个类中的所有属性和方法: ...
- java学习之反射机制
java语言区别于C,C++等准静态语言的最大特点就是java的反射机制.静态语言的最直接定义就是不能在运行时改变程序结构或变量的类型.按照这样的定义,python,ruby是动态语言,C,C++,J ...
- java 中利用反射机制获取和设置实体类的属性值
摘要: 在java编程中,我们经常不知道传入自己方法中的实体类中到底有哪些方法,或者,我们需要根据用户传入的不同的属性来给对象设置不同的属性值,那么,java自带的反射机制可以很方便的达到这种目的,同 ...
随机推荐
- CentOS7 安装nginx部署vue项目
简单描述:代码开发完了,需要环境来运行测试.服务器上没有nginx,搞起搞起. 在Centos下,yum源不提供nginx的安装,可以通过切换yum源的方法获取安装.也可以通过直接下载安装包的方法 ...
- 解决element上传功能清除单个文件的问题
今天,在使用 element 实现一个上传文件的功能. 接下来,要对上传的文件列表,实现删除单文件的功能. 看了 element 开发文档,发现 on-remove 没有特别的详细的说明,刚开始使用 ...
- 宿主机连接docker中的mysql
宿主机连接docker中的mysql dokcer安装mysql docker run \ --name mysql \ -v $PWD/mysql:/var/lib/mysql \ -p 330 ...
- Laragon修改配置快速创建其他框架的项目
配置方式 依葫芦画瓢,如添加thinkPHP: # Thinkphp Thinkphp 3.2=composer create-project topthink/thinkphp %s Thinkph ...
- MySQL Front远程连接数据库
连接前需要先配置一下服务器端的数据库 进入mysql数据库,选择mysql mysql> use mysql; 选择 host 表 mysql> select host from user ...
- 关闭,centos yum的自动更新
今天我虚拟机提示我满了,,,打开磁盘分析器一看,yum的更新目录满了,本地虚拟跟生产环境的版本完全一致,所以我也不打算更新,找一下命令,得先安装yum-cron ,然后再禁止更新 [root@loca ...
- luogu P3645 [APIO2015]雅加达的摩天楼 分块 根号分治
LINK:雅加达的摩天楼 容易想到设\(f_{i,j}\)表示第i个\(doge\)在第j层楼的最小步数. 转移显然是bfs.值得一提的是把初始某层的\(doge\)加入队列 然后转移边权全为1不需要 ...
- MyBatis-Plus使用(4)-集成SpringBoot
我这里使用的MyBatis-Plus是当前最新的3.2.0版本, 1. 引入需要的jar,基础jar包括: <dependencies> <dependency> <gr ...
- 执行HiveSQL出现的问题
-- ::, INFO [main] org.apache.hadoop.hive.ql.exec.ReduceSinkOperator: RECORDS_OUT_INTERMEDIATE:, -- ...
- odoo13之文件预览widget/模块
本文示例代码可查看github仓库:odoo13_file_preview 文件预览效果图展示 效果描述: 1.当点击图片或者文件时展开图片. 2.当点击关闭按钮时关闭图片预览. 3.当点击下载按钮时 ...