【JAVA基础】反射机制
2017-12-24 21:17
120 查看
Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有方法和属性;这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制
反射的作用:
1、调用一些私有方法,实现黑科技。比如双卡短信发送、设置状态栏颜色、自动挂电话等。
2、实现序列化与反序列化,比如PO的ORM,Json解析等
3、实现跨平台兼容,比如jdk中的SocketImpl的实现
4、通过xml或注解,实现依赖注入,注解处理,动态代理,单元测试等功能。比如Retrofit、Spring或者Dagger
2、对象照镜子后(反射)可以得到的信息:某个类的数据成员名、方法和构造器、某个类到底实现了哪些接口。
3、对于每个类而言。jre都为其保留一个不变的class类型的对象。一个class对象包含了特定某个类的有关信息
4、class对象只能由系统建立对象
5、一个类在jvm中只会有一个class实例
[b]反射机制获取类的三种方法[/b]
1、通过类名
2、通过getClass()
3、通过全类名获取
[b]利用newInstance创建对象:调用的类必须有无参的构造器[/b]
无参构造器:Person{name=’null’,age=0}
类加载器详解:http://blog.csdn.net/ochangwen/article/details/51473120
1、Class.forName
Class.forName可以通过寻找Class对象,比如Class.forName(“java.lang.String”)。
在JDK的源码实现中,可以发现最终调用的是native方法forName0(),它在JVM中调用的实际是findClassFromClassLoader(),原理与ClassLoader的流程一样。
2、getDeclareFields的实现
在jdk源码中,可以知道class.getDeclaredFields()方法实际调用的是native方法getDeclaredFields0(),它在JVM主要实现步骤如下:
(1)根据class结构体信息,获取field_count与fields[]字段,这个字段早已在load过程中被放入了
(2)根据field_count的大小分配内存、创建数组
(3)将数组进行forEach循环,通过fields[]中的信息依次创建Object对象
(4)返回数组指针
3、Method.invoke的实现
以下为无同步、无异常的情况下调用的步骤:
(1)创建Frame
(2)如果对象flag为native,交给native_handler进行处理
(3)在frame中执行java代码
(4)弹出Frame
(5)返回执行结果的指针
4、class.newInstance的实现
(1)检测权限、预分配空间大小等参数
(2)创建Object对象,并分配空间
(3)通过Method.invoke调用构造函数(())
(4)返回Object指针
一、什么是java反射
反射使程序代码能够接入装载到JVM中的类的内部信息,允许在编写与执行时,而不是源代码中选定的类协作的代码,是以开发效率换运行效率的一种手段。这使反射称为构建灵活应用的主要工具。反射的作用:
1、调用一些私有方法,实现黑科技。比如双卡短信发送、设置状态栏颜色、自动挂电话等。
2、实现序列化与反序列化,比如PO的ORM,Json解析等
3、实现跨平台兼容,比如jdk中的SocketImpl的实现
4、通过xml或注解,实现依赖注入,注解处理,动态代理,单元测试等功能。比如Retrofit、Spring或者Dagger
二、class类
1、class是一个描述类的类(也就是描述类本身),封装了描述方法的Method,描述字段的Field,描述构造类的Constructor等属性2、对象照镜子后(反射)可以得到的信息:某个类的数据成员名、方法和构造器、某个类到底实现了哪些接口。
3、对于每个类而言。jre都为其保留一个不变的class类型的对象。一个class对象包含了特定某个类的有关信息
4、class对象只能由系统建立对象
5、一个类在jvm中只会有一个class实例
[b]反射机制获取类的三种方法[/b]
1、通过类名
2、通过getClass()
3、通过全类名获取
/** * 反射机制获取类有三种方法 */ @Test public void testGetClass() throws ClassNotFoundException { Class clazz = null; //1 直接通过类名.Class的方式得到 clazz = Person.class; System.out.println("通过类名: " + clazz); //2 通过对象的getClass()方法获取,这个使用的少(一般是传的是Object,不知道是什么类型的时候才用) Object obj = new Person(); clazz = obj.getClass(); System.out.println("通过getClass(): " + clazz); //3 通过全类名获取,用的比较多,但可能抛出ClassNotFoundException异常 clazz = Class.forName("com.java.reflection.Person"); System.out.println("通过全类名获取: " + clazz); }
[b]利用newInstance创建对象:调用的类必须有无参的构造器[/b]
无参构造器:Person{name=’null’,age=0}
/** * Class类的newInstance()方法,创建类的一个对象。 */ @Test public void testNewInstance() throws ClassNotFoundException, IllegalAccessException, InstantiationException { Class clazz = Class.forName("com.java.reflection.Person"); //使用Class类的newInstance()方法创建类的一个对象 //实际调用的类的那个 无参数的构造器(这就是为什么写的类的时候,要写一个无参数的构造器,就是给反射用的) //一般的,一个类若声明了带参数的构造器,也要声明一个无参数的构造器 Object obj = clazz.newInstance(); System.out.println(obj); }
三、ClassLoader类加载器
类加载器是用来把类装载进jvm的。jvm规范定义了两种类型的类装载器:启动类家载器和用户自定义加载器。jvm在运行时会产生3个类加载器组成的初始化加载器层次结构,如下图所示:类加载器详解:http://blog.csdn.net/ochangwen/article/details/51473120
/** * ClassLoader类装载器 */ @Test public void testClassLoader1() throws ClassNotFoundException, IOException { //1、获取一个系统的类加载器 ClassLoader classLoader = ClassLoader.getSystemClassLoader(); System.out.println("系统的类加载器-->" + classLoader); //2、获取系统类加载器的父类加载器(扩展类加载器(extensions classLoader)) classLoader = classLoader.getParent(); System.out.println("扩展类加载器-->" + classLoader); //3、获取扩展类加载器的父类加载器 //输出为Null,无法被Java程序直接引用 classLoader = classLoader.getParent(); System.out.println("启动类加载器-->" + classLoader); // //4、测试当前类由哪个类加载器进行加载 ,结果就是系统的类加载器 classLoader = Class.forName("com.java.reflection.Person").getClassLoader(); System.out.println("当前类由哪个类加载器进行加载-->"+classLoader); //5、测试JDK提供的Object类由哪个类加载器负责加载的 classLoader = Class.forName("java.lang.Object").getClassLoader(); System.out.println("JDK提供的Object类由哪个类加载器加载-->" + classLoader); }
四、反射在native的实现
反射在java中可以直接调用,不过最终调用的认识native方法,以下为主流反射操作的实现1、Class.forName
Class.forName可以通过寻找Class对象,比如Class.forName(“java.lang.String”)。
在JDK的源码实现中,可以发现最终调用的是native方法forName0(),它在JVM中调用的实际是findClassFromClassLoader(),原理与ClassLoader的流程一样。
2、getDeclareFields的实现
在jdk源码中,可以知道class.getDeclaredFields()方法实际调用的是native方法getDeclaredFields0(),它在JVM主要实现步骤如下:
(1)根据class结构体信息,获取field_count与fields[]字段,这个字段早已在load过程中被放入了
(2)根据field_count的大小分配内存、创建数组
(3)将数组进行forEach循环,通过fields[]中的信息依次创建Object对象
(4)返回数组指针
3、Method.invoke的实现
以下为无同步、无异常的情况下调用的步骤:
(1)创建Frame
(2)如果对象flag为native,交给native_handler进行处理
(3)在frame中执行java代码
(4)弹出Frame
(5)返回执行结果的指针
4、class.newInstance的实现
(1)检测权限、预分配空间大小等参数
(2)创建Object对象,并分配空间
(3)通过Method.invoke调用构造函数(())
(4)返回Object指针
相关文章推荐
- java的反射和内省机制基础探密
- JAVA基础--JAVA中的反射机制详解
- Java基础系列:(3)反射机制的简单总结
- Java基础知识——反射机制
- java基础知识-反射机制
- JAVA基础--JAVA中的反射机制详解
- JAVA基础--JAVA中的反射机制详解
- Java基础知识――类装载器与反射机制
- Java进阶之reflection(反射机制)——反射概念与基础
- Java基础笔记 – 通过反射机制修改类中的私有属性的值
- JAVA基础--反射机制
- java基础中的反射机制
- Java基础_13_反射机制
- JAVA基础 (三)反射 深入解析反射机制
- JAVA基础--JAVA中的反射机制详解
- JAVA基础--JAVA中的反射机制详解
- 黑马程序员_java基础——反射机制
- java基础学习笔记——反射机制
- java面试基础-Java中的反射机制
- Java语言基础-反射机制、正则表达式