Java动态性之--反射机制
1. 动态语言
程序运行时,可以改变结构或变量类型。典型的语言:
- Python、ruby、javascript等
- 如下javascript代码
function test(){ var s = "var a=3;var b=5;alert(a+b);"; eval(s); }
- C,C++,java不是动态语言,java可以称之为“准动态语言”。但是java有一定的动态性,我们可以利用反射机制、字节码操作获得类似动态语言的特性
- java的动态性让编程的时候更加灵活!
2. 反射机制reflection
- 指的是可以于运行时加载、探知、使用编译其完全未知的类。
- 程序在运行状态中,可以动态加载一个只有名称的类,对于任意一个已加载的类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;
Class c = Class.forName(cn.stu.test.User);
- 加载完类之后,在堆内存中,就产生了一个Class类型的对象(一个类只有一个Class对象),这个对象就包含了完整的类的结构信息,我们可以通过这个对象看到类的结构。这个对象就像一面镜子,透过这个镜子看到类的结构,所有,我们形象的称之为:反射
例1:
public class Demo01 {
public static void main(String[] args) {
String path = "cn.stu.ref.bean.User"; try {
//方法一
Class clazz = Class.forName(path);
//
/**
* ==================================
* 对象时表示或封装一些数据。一个类被加载后,
* JVM会创建一个对应该类的Class对象
* 类的整个结构信息会会放到对应的Class对象中。
* 这个Class对象就是一面镜子一样,
* 通过这面镜子我们可以看到对应类的全部信息
* ===================================
*/
System.out.println(clazz.hashCode());
//一个类只对应一个Class对象
Class clazz2 = Class.forName(path);
System.out.println(clazz2.hashCode()); //方法二
Class strClass = String.class;
Class strClass2 = path.getClass();
System.out.println(strClass==strClass2); } catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
3. Class类介绍
当一个class被加载,或当加载器(class loader)的defineClass()被JVM调用,JVM便自动产生一个Class对象
Class类似Reflection的根源
针对任何你想动态加载、运行的类,唯有先获得相应的Class对象
Class类的对象如何获取?
- 运用getClass()
- 运用Class.forName() --常用
- 运用.class语法
例2:
public class Demo02 { public static void main(String[] args) {
String path = "cn.stu.ref.bean.User";
try {
Class clazz = Class.forName(path); //获取类的名称
System.out.println(clazz.getName());//类名+包名
System.out.println(clazz.getSimpleName());//类名 //获取属性名
Field[] fields = clazz.getFields(); //只能获得public的属性
Field[] fields2 = clazz.getDeclaredFields();//获得所有属性
Field field = clazz.getDeclaredField("name");//获取指定name属性 //获取方法名称
Method[] method = clazz.getDeclaredMethods();
Method m1 = clazz.getDeclaredMethod("getName", null);
//如果方法有参,则必须传递参数类型对应的class对象
Method m2 = clazz.getDeclaredMethod("setName", String.class); //获取构造器
Constructor[] constructors = clazz.getDeclaredConstructors();
Constructor c = clazz.getDeclaredConstructor(int.class,int.class,String.class); } catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
例3:
public class Demo03 {
public static void main(String[] args) {
String path = "cn.stu.ref.bean.User"; try {
Class clazz = Class.forName(path); //通过反射API调用构造方法,构造对象
User u = (User) clazz.newInstance();//其实是调用了User的无参构造方法 Constructor c = clazz.getDeclaredConstructor(int.class,int.class,String.class);
User u2 = (User) c.newInstance(1001,18,"张三"); //通过反射API调用普通方法
User u3 = (User) clazz.newInstance();
Method method = clazz.getDeclaredMethod("setName", String.class);
method.invoke(u3,"李四"); //u3.setName("李四") //通过反射API操作属性
User u4 = (User) clazz.newInstance();
Field f = clazz.getDeclaredField("name");
f.setAccessible(true);//不做安全检查,直接访问
f.set(u4, "二麻子"); //通过反射直接写属性
String name = u4.getName();
String name2 = (String) f.get(u4); //通过反射直接读属性的值
} catch (Exception e) {
e.printStackTrace();
}
}
}
4. 反射机制性能问题
- setAccessible
- 启动和金庸访问安全检查的开关,值为true 则指示反射的对象在使用时应该取消java语言访问检查,值为false 则指示反射的对象应该实施java语言访问检查。并不是true就能访问,false就不能访问。
- 禁止安全检查,可以提高反射的运行速度
- 可以考虑使用: cglib/javaassist字节码操作
例4:
/**
* 通过跳过安全检查,提高反射效率
* 三种执行方法的效率差异比较
*/
public class Demo04 { public static void test01(){
User u = new User(); long startTime = System.currentTimeMillis(); for (int i = 0; i < 1000000000L; i++) {
u.getName();
} long endTime = System.currentTimeMillis();
System.out.println("普通方法调用,执行10亿次,耗时:"+(endTime-startTime)+"ms");
} public static void test02() throws Exception{
User u = new User();
Class clazz = u.getClass();
Method m = clazz.getDeclaredMethod("getName", null);
// m.setAccessible(true); long startTime = System.currentTimeMillis(); for (int i = 0; i < 1000000000L; i++) {
m.invoke(u, null);
} long endTime = System.currentTimeMillis();
System.out.println("反射动态方法调用,执行10亿次,耗时:"+(endTime-startTime)+"ms");
} public static void test03() throws Exception{
User u = new User();
Class clazz = u.getClass();
Method m = clazz.getDeclaredMethod("getName", null);
m.setAccessible(true); //不需要执行访问安全检查 long startTime = System.currentTimeMillis(); for (int i = 0; i < 1000000000L; i++) {
m.invoke(u, null);
} long endTime = System.currentTimeMillis();
System.out.println("反射动态方法调用,跳过安全检查,执行10亿次,耗时:"+(endTime-startTime)+"ms");
} public static void main(String[] args) throws Exception {
test01();
test02();
test03();
}
}
输出结果:
普通方法调用,执行10亿次,耗时:6665ms
反射动态方法调用,执行10亿次,耗时:62947ms
反射动态方法调用,跳过安全检查,执行10亿次,耗时:11864ms
5. 反射操作泛型
- java采用泛型擦除的机制来引入泛型。java中的泛型仅仅是给编译器javac使用的,确保数据的安全性和免去强制类型转换的麻烦,但是,一旦编译完成,所有的和泛型有关的类型全部擦除。
- 为了通过反射操操作这些类型以迎合实际开发的需要,java就新增了ParameterzedType,GenericArrayType,TypeVariable和WildcardType几种类型来代表不能被诡异到Class类中的类型但是又和原始类型齐名的类型。
- ParmterizedType: 表示一种参数化的类型,比如Collection<String>
- GenericArrayType: 表示一种元素类型是参数化类型或者类型变量的数组类型
- TypeVariable:是各种类型变量的公共父接口
- WildcardType:代表一种通配符类型表达式
Java动态性之--反射机制的更多相关文章
- Java动态性之反射机制(reflection)
说到反射机制,第一次接触的人可能会比较懵,反射?什么反射?怎么反射?反射是干嘛的?下面我将在这篇文章中讲讲Java的反射机制 不过在这之前,还有一个问题需要解决,标题名中的动态性,说起动态性,我先介绍 ...
- 小白都能学会的Java注解与反射机制
前言 Java注解和反射是很基础的Java知识了,为何还要讲它呢?因为我在面试应聘者的过程中,发现不少面试者很少使用过注解和反射,甚至有人只能说出@Override这一个注解.我建议大家还是尽量能在开 ...
- java中的反射机制在Android开发中的用处
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反 ...
- 黑马程序员——【Java高新技术】——反射机制
---------- android培训.java培训.期待与您交流! ---------- 一.概述 1.Java反射机制:是指“在运行状态中”,对于任意一个类,都能够知道这个类中的所有属性和方法: ...
- Java 中的反射机制
JAVA反射机制 JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法:这种动态获取的信息以及动态调用对象的方法的功能称为ja ...
- JAVA类型信息——反射机制
JAVA类型信息——反射机制 一.反射机制概述 1.反射机制:就是java语言在运行时拥有的一项自我观察的能力,java通过这种能力彻底了解程序自身的情况,并为下一步的动作做准备. 2.反射机制的功能 ...
- 浅说Java中的反射机制(二)
写过一篇Java中的反射机制,不算是写,应该是抄了,因为那是别人写的,这一篇也是别人写的,摘抄如下: 引自于Java基础--反射机制的知识点梳理,作者醉眼识朦胧.(()为我手记) 什么是反射? 正常编 ...
- 浅说Java中的反射机制(一)
在学习传智播客李勇老师的JDBC系列时,会出现反射的概念,由于又是第一次见,不免感到陌生.所以再次在博客园找到一篇文章,先记录如下: 引用自java中的反射机制,作者bingoideas.(()为我手 ...
- java学习之反射机制
java语言区别于C,C++等准静态语言的最大特点就是java的反射机制.静态语言的最直接定义就是不能在运行时改变程序结构或变量的类型.按照这样的定义,python,ruby是动态语言,C,C++,J ...
随机推荐
- HGOI20180822 五校联考卷
T1 [题目意思]给出下列程序片段,预测程序运行结果 输入文件为T(T<=200)组数据,每组数据有个n(n<=1014) 输出文件为T行,每行一个数据,表示fun(n)的值 simple ...
- 开发常用镜像资源替换为国内开源镜像(yum,compose,maven,docker,android sdk,npm,国内开源镜像汇总)
一.国内开源镜像站点汇总 阿里云开源镜像站 (http://mirrors.aliyun.com/)网易开源镜像站 (http://mirrors.163.com/)中国科学技术大学开源镜像站 (ht ...
- 【转】Android 编程下的代码混淆
什么是代码混淆 代码混淆(Obfuscated code)亦称花指令,是将计算机程序的代码,转换成一种功能上等价,但是难于阅读和理解的形式的行为.代码混淆可以用于程序源代码,也可以用于程序编译而成的中 ...
- Java基本语法---个人参考资料
Java语言基础组成:关键字.标识符.注释.常量和变量.运算符.语句.函数.数组 一.标识符 标识符是在程序中自定义的一些名称,由大小写字母[a-zA-Z],数字[0-9],下划线[ _ ],特殊字符 ...
- mongodb 设置用户密码权限
1 设置管理员账户 use admindb.createUser({ user: "useradmin", pwd: "adminpassword", role ...
- 关闭ubuntu dash 方法
因为ubuntu默认的sh是连接到dash的,又因为dash跟bash的不兼容所以出错了.执行时可以把sh换成bash 文件名.sh来执行.成功.dash是什么东西,查了一下,应该也是一种shell, ...
- MFC Activex 开发、ocx打包成cab、部署、测试、自动升级
小小抱怨下:也许是MFC现在用的人少的缘故.在国内和国外都基本上找不到什么全的资料.特别是ocx打包成Cab时的安装文件inf的编写方面,国内基本上是copy,抄的还一知半解.查找个资源真心的累啊.现 ...
- 在同一个表中将varchar2类型的数据转存到blob类型的字段中
用一条修改语句即可:update t_content set f_body=rawtohex(f_check) where f_type in (0,4)此处须用rawtohex()函数将f_chec ...
- nova-api源码分析(APP的创建)
目录结构如下: 上面介绍了nova-api发布所用到的一些lib库,有了上面的基础知识,再来分析nova-api的发布流程,就比较轻松了.nova-api可以提供多种api服务:ec2, osapi_ ...
- python操作txt文件中数据教程[1]-使用python读写txt文件
python操作txt文件中数据教程[1]-使用python读写txt文件 觉得有用的话,欢迎一起讨论相互学习~Follow Me 原始txt文件 程序实现后结果 程序实现 filename = '. ...