目录

  • 1、什么是反射?  
  • 2、反射能做什么?   
  • 3、反射的具体实现
  • 4、根据反射获取父类属性
  • 4、反射总结

  反射反射,程序员的快乐!

1、什么是反射?  

  Java反射就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;并且能改变它的属性。而这也是Java被视为动态(或准动态,为啥要说是准动态,因为一般而言的动态语言定义是程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言。从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言。)语言的一个关键性质。

2、反射能做什么?   

  我们知道反射机制允许程序在运行时取得任何一个已知名称的class的内部信息,包括包括其modifiers(修饰符),fields(属性),methods(方法)等,并可于运行时改变fields内容或调用methods。那么我们便可以更灵活的编写代码,代码可以在运行时装配,无需在组件之间进行源代码链接,降低代码的耦合度;还有动态代理的实现等等;但是需要注意的是反射使用不当会造成很高的资源消耗!

3、反射的具体实现

  下面是一个基本的类 Person

 
 1 package com.ys.reflex;
2 public class Person {
3 //私有属性
4 private String name = "Tom";
5 //公有属性
6 public int age = 18;
7 //构造方法
8 public Person() {
9 }
10 //私有方法
11 private void say(){
12 System.out.println("private say()...");
13 }
14 //公有方法
15 public void work(){
16 System.out.println("public work()...");
17 }
18 }
 

①、得到 Class 的三种方式

 
 1 //1、通过对象调用 getClass() 方法来获取,通常应用在:比如你传过来一个 Object
2 // 类型的对象,而我不知道你具体是什么类,用这种方法
3   Person p1 = new Person();
4   Class c1 = p1.getClass();
5
6 //2、直接通过 类名.class 的方式得到,该方法最为安全可靠,程序性能更高
7 // 这说明任何一个类都有一个隐含的静态成员变量 class
8   Class c2 = Person.class;
9
10 //3、通过 Class 对象的 forName() 静态方法来获取,用的最多,
11 // 但可能抛出 ClassNotFoundException 异常
12   Class c3 = Class.forName("com.ys.reflex.Person");
 

需要注意的是:一个类在 JVM 中只会有一个 Class 实例,即我们对上面获取的 c1,c2,c3进行 equals 比较,发现都是true

②、通过 Class 类获取成员变量、成员方法、接口、超类、构造方法等

查阅 API 可以看到 Class 有很多方法:

  getName():获得类的完整名字。
  getFields():获得类的public类型的属性。
  getDeclaredFields():获得类的所有属性。包括private 声明的和继承类
  getMethods():获得类的public类型的方法。
  getDeclaredMethods():获得类的所有方法。包括private 声明的和继承类
  getMethod(String name, Class[] parameterTypes):获得类的特定方法,name参数指定方法的名字,parameterTypes 参数指定方法的参数类型。
  getConstructors():获得类的public类型的构造方法。
  getConstructor(Class[] parameterTypes):获得类的特定构造方法,parameterTypes 参数指定构造方法的参数类型。
  newInstance():通过类的不带参数的构造方法创建这个类的一个对象。

我们通过一个例子来综合演示上面的方法:

 1 //获得类完整的名字
2 String className = c2.getName();
3 System.out.println(className);//输出com.ys.reflex.Person
4
5 //获得类的public类型的属性。
6 Field[] fields = c2.getFields();
7 for(Field field : fields){
8 System.out.println(field.getName());//age
9 }
10
11 //获得类的所有属性。包括私有的
12 Field [] allFields = c2.getDeclaredFields();
13 for(Field field : allFields){
14 System.out.println(field.getName());//name age
15 }
16
17 //获得类的public类型的方法。这里包括 Object 类的一些方法
18 Method [] methods = c2.getMethods();
19 for(Method method : methods){
20 System.out.println(method.getName());//work waid equls toString hashCode等
21 }
22
23 //获得类的所有方法。
24 Method [] allMethods = c2.getDeclaredMethods();
25 for(Method method : allMethods){
26 System.out.println(method.getName());//work say
27 }
28
29 //获得指定的属性
30 Field f1 = c2.getField("age");
31 System.out.println(f1);
32 //获得指定的私有属性
33 Field f2 = c2.getDeclaredField("name");
34 //启用和禁用访问安全检查的开关,值为 true,则表示反射的对象在使用时应该取消 java 语言的访问检查;反之不取消
35 f2.setAccessible(true);
36 System.out.println(f2);
37
38 //创建这个类的一个对象
39 Object p2 = c2.newInstance();
40 //将 p2 对象的 f2 属性赋值为 Bob,f2 属性即为 私有属性 name
41 f2.set(p2,"Bob");
42 //使用反射机制可以打破封装性,导致了java对象的属性不安全。
43 System.out.println(f2.get(p2)); //Bob
44
45 //获取构造方法
46 Constructor [] constructors = c2.getConstructors();
47 for(Constructor constructor : constructors){
48 System.out.println(constructor.toString());//public com.ys.reflex.Person()
49 }

4、根据反射获取父类属性

父类 Parent.java

public class Parent {
public String publicField = "parent_publicField";
protected String protectField = "parent_protectField";
String defaultField = "parent_defaultField";
private String privateField = "parent_privateField"; }

子类 Son.java

1 public class Son extends Parent {
2 }

测试类:

public class ReflectionTest {

    @Test
public void testGetParentField() throws Exception{
Class c1 = Class.forName("com.ys.model.Son");
//获取父类私有属性值
System.out.println(getFieldValue(c1.newInstance(),"privateField"));
} public static Field getDeclaredField(Object obj,String fieldName) {
Field field = null;
Class c = obj.getClass();
for(; c != Object.class ; c = c.getSuperclass()){
try {
field = c.getDeclaredField(fieldName);
field.setAccessible(true);
return field;
}catch (Exception e){
//这里甚么都不要做!并且这里的异常必须这样写,不能抛出去。
//如果这里的异常打印或者往外抛,则就不会执行c = c.getSuperclass(),最后就不会进入到父类中了
}
}
return null;
}
public static Object getFieldValue(Object object,String fieldName) throws Exception{
Field field = getDeclaredField(object,fieldName); return field.get(object);
}
}

5、反射总结

灵活使用反射能让我们代码更加灵活,这里比如JDBC原生代码注册驱动,hibernate 的实体类,Spring 的 AOP等等都有反射的实现。但是凡事都有两面性,反射也会消耗系统的性能,增加复杂性等,合理使用才是真!

作者:YSOcean
本文版权归作者所有,欢迎转载,但未经作者同意不能转载,否则保留追究法律责任的权利。

【转载】Java 反射详解的更多相关文章

  1. Java 反射详解 转载

    java 反射 定义 功能 示例 概要: Java反射机制详解 | |目录 1反射机制是什么 2反射机制能做什么 3反射机制的相关API ·通过一个对象获得完整的包名和类名 ·实例化Class类对象 ...

  2. java 反射详解

    反射的概念和原理 类字节码文件是在硬盘上存储的,是一个个的.class文件.我们在new一个对象时,JVM会先把字节码文件的信息读出来放到内存中,第二次用时,就不用在加载了,而是直接使用之前缓存的这个 ...

  3. java反射 详解!!!!

    java反射(特别通俗易懂) 反射是框架设计的灵魂 (使用的前提条件:必须先得到代表的字节码的Class,Class类用于表示.class文件(字节码)) 一.反射的概述 JAVA反射机制是在运行状态 ...

  4. java反射详解及说明

    首先写一个Person类: package lltse.base.reflectdemo; public class Person { private String name ="张三&qu ...

  5. 《Java基础知识》Java 反射详解

    定义 JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意方法和属性:这种动态获取信息以及动态调用对象方法的功能称为java语言的反射 ...

  6. java反射详解

    本篇文章依旧采用小例子来说明,因为我始终觉的,案例驱动是最好的,要不然只看理论的话,看了也不懂,不过建议大家在看完文章之后,在回过头去看看理论,会有更好的理解. 下面开始正文. [案例1]通过一个对象 ...

  7. java反射详解(转)

    本篇文章依旧采用小例子来说明,因为我始终觉的,案例驱动是最好的,要不然只看理论的话,看了也不懂,不过建议大家在看完文章之后,在回过头去看看理论,会有更好的理解. 下面开始正文. [案例1]通过一个对象 ...

  8. Java反射详解及应用示例

    反射是Java中最重要的内容之一,了解反射原理对我们学习各种框架具有很大的帮助 反射的原理: 反射应用示例: import java.lang.reflect.Constructor; import ...

  9. 【转】java反射详解

    转自:http://www.cnblogs.com/rollenholt/archive/2011/09/02/2163758.html 本篇文章依旧采用小例子来说明,因为我始终觉的,案例驱动是最好的 ...

随机推荐

  1. Atom编辑器折腾记_(15)JS代码片段补全(插件:javascript-snippets)

    题外话 这款插件就比較重量级了-.用熟悉了写原生JS的效率要提升非常多--并且,不仅支持JS还包括了nodejs snippet javascript-snippets 插件作者: zenorocha ...

  2. C++ 句柄类的原理以及设计

    句柄类存在的意义是为了弥补将派生类对象赋给基类对象时发生的切片效应.比如以下的程序: multimap<Base> basket; Base base; Derived derive; b ...

  3. HDU 5289 Assignment (ST算法区间最值+二分)

    题目链接:pid=5289">http://acm.hdu.edu.cn/showproblem.php?pid=5289 题面: Assignment Time Limit: 400 ...

  4. CreateWindowEx和CreateWindow的区别

    CreateWindowEx 函数功能:该函数创建一个具有扩展风格的重叠式窗口.弹出式窗口或子窗口,其他与 CreateWindow函数相同.关于创建窗口和其他参数的内容,请参看CreateWindo ...

  5. 0x6A 网络流初步

    CH Round #17-C 这个算是一个技能点吧,不点不会,点了就没什么了.懒得写看书吧书上的1应该是0... 我又回来了太懒了不想翻书还是写写吧 必须边的判定条件:该边流量为0且两端的点在残余网络 ...

  6. multiple web application host under the same website on IIS (authentication mode)

    第一种方式,修改forms的name how to set the forms authentication cookie path assume you have already solved th ...

  7. Android WiFi开发教程(三)——WiFi热点数据传输

    在上一篇文章中介绍了WiFi的搜索和连接,如果你还没阅读过,建议先阅读上一篇Android WiFi开发教程(二)——WiFi的搜索和连接.本篇接着简单介绍手机上如何通过WiFi热点进行数据传输. 跟 ...

  8. P2831 愤怒的小鸟 状压dp

    这个题主要是预处理比较复杂,先枚举打每只鸟用的抛物线,然后找是否有一个抛物线经过两只鸟,然后就没了. 题干: 题目描述 Kiana 最近沉迷于一款神奇的游戏无法自拔. 简单来说,这款游戏是在一个平面上 ...

  9. 97. ExtJS之EditorGridPanel afteredit属性

    转自:https://zccst.iteye.com/blog/1328869 1. 之前大多用Ext.grid.GridPanel,现在需要可编辑功能,发现比以前稍复杂一些. 就是需要对指定列进行可 ...

  10. A. Jeff and Digits(cf)

    A. Jeff and Digits time limit per test 1 second memory limit per test 256 megabytes input standard i ...