反射技术其实就是动态加载一个指定的类,并获取该类中的所有内容。而且将字节码文件封装成对象,并将字节码文件中的内容都封装成对象,这样便于操作这些成员,简单来说:反射技术可以对一个类进行解剖,反射大大增强了应用程序的可扩展性。
反射技术的原理如下图所示:
但是要想要对字节码文件进行解剖,必须要有字节码文件对象. 如何获取字节码文件对象呢?
要读取的类文件源码:
1 package Reflect; 2 3 public class Person { 4 5 /** 6 * @param args 7 */ 8 private String name; 9 private int age; 10 public Person(){ 11 System.out.println("Construcor run.."); 12 } 13 public Person(String name,int age){ 14 this.name=name; 15 this.age=age; 16 System.out.println("Person param run..."); 17 } 18 public static void method(){ 19 System.out.println("method run..."); 20 } 21 public static void paramMethod(String name,int age){ 22 System.out.println("name="+name+"age:"+age); 23 } 24 public static void staticMethod(){ 25 System.out.println("static run"); 26 } 27 public void show(){ 28 System.out.println(name+"Method show run.."+age); 29 } 30 31 }
获取字节码文件对象有三种方式:
(1)
/*
* 获取字节码对象的方式:
* 1,Object类中的getClass()方法的。
* 想要用这种方式,必须要明确具体的类,并创建对象。
* 麻烦
*/
1 public static void getObject_1() { 2 Person p=new Person(); 3 Class<? extends Person> classz=p.getClass(); 4 System.out.println(classz); 5 Person p1=new Person(); 6 Class<? extends Person> classz1=p.getClass(); 7 System.out.println(classz1); 8 System.out.println(classz==classz1); 9 }
(2)
/*
* 方式二:
* 任何数据类型(基本数据类型和引用数据类型)都具备一个静态的属性.class来获取其对应的Class对象。
* 相对简单,但是还是要明确用到类中的静态成员。
* 还是不够扩展。
*
*/
1 public static void getObject_2() { 2 3 Class classz=Person.class; 4 Class classz1=Person.class; 5 System.out.println(classz==classz1); 6 }
(3)
/*
* 方式三:
* 只要通过给定的类的 字符串名称就可以获取该类,更为扩展。
* 可是用Class类中的方法完成。
* 该方法就是forName.
* 这种方式只要有名称即可,更为方便,扩展性更强。
*/
1 public static void getObject_3() throws ClassNotFoundException { 2 String classname="Reflect.Person"; 3 Class classz=Class.forName(classname); 4 System.out.println(classz); 5 }
获取Class中的构造函数初始化对象:
(1)调用空参数的构造函数:使用Class类中的newInstance()方法
//早期:new时候,先根据被new的类的名称找寻该类的字节码文件,并加载进内存,
// 并创建该字节码文件对象,并接着创建该字节文件的对应的Person对象.
1 //现在: 2 String name = "cn.itcast.bean.Person"; 3 //找寻该名称类文件,并加载进内存,并产生Class对象。 4 Class clazz = Class.forName(name); 5 //如何产生该类的对象呢? 6 Object obj = clazz.newInstance();
(2)调用带参数的构造函数:先要获取指定参数列表的构造函数对象,然后通过该构造函数的对象的newInstance(实际参数)进行对象的初始化
/* * 当获取指定名称对应类中的所体现的对象时, * 而该对象初始化不使用空参数构造该怎么办呢? * 既然是通过指定的构造 函数进行对象的初始化, * 所以应该先获取到该构造函数。 通过字节码文件对象即可完成。 * 该方法是:getConstructor(paramterTypes); * */
1 //带参数初始化新创建的对象 2 public static void createNewObject_param() throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { 3 String classname="Reflect.Person"; 4 Class classz=Class.forName(classname); 5 Constructor constructor=classz.getConstructor(String.class,int.class); 6 constructor.newInstance("Java",30); 7 }
获取反射类的字段:
1 public static void getFiledDemo() throws ClassNotFoundException, 2 NoSuchFieldException, SecurityException, InstantiationException, 3 IllegalAccessException { 4 Class classz = Class.forName("Reflect.Person"); 5 Field field = null; 6 field = classz.getDeclaredField("age"); 7 field.setAccessible(true); 8 Object obj = classz.newInstance(); 9 field.set(obj, 89); 10 Object o = field.get(obj); 11 System.out.println(o); 12 }
获取反射类的成员方法:
(1)获取空参数一般方法
1 private static void getMethodDemo_2() throws Exception { 2 Class clazz = Class.forName("Reflect.Person"); 3 4 Method method = clazz.getMethod("show", null);// 获取空参数一般方法。 5 6 // Object obj = clazz.newInstance(); 7 Constructor constructor = clazz.getConstructor(String.class, int.class); 8 Object obj = constructor.newInstance("linux", 37); 9 10 method.invoke(obj, null); 11 }
(2)获取带参数的一般方法
1 private static void getMethodDemo_3() throws Exception { 2 3 Class clazz = Class.forName("Reflect.Person"); 4 5 Method method = clazz.getMethod("paramMethod", String.class, int.class); 6 7 Object obj = clazz.newInstance(); 8 9 method.invoke(obj, "Ruby", 89); 10 }
(3)获取反射类的公有、私有方法
1 private static void getMethodDemo() throws ClassNotFoundException { 2 Class classz = Class.forName("Reflect.Person"); 3 Method[] methods = classz.getMethods();// 获取反射类中所有共有的方法 4 methods = classz.getDeclaredMethods();// 获取本类中包括私有的所有的方法 5 for (Method method : methods) { 6 System.out.println(method); 7 } 8 }
本文为博主原创文章,转载请注明出处:http://www.cnblogs.com/ysw-go/
1、本博客的原创原创文章,都是本人平时学习所做的笔记,如有错误,欢迎指正。
2、如有侵犯您的知识产权和版权问题,请通知本人,本人会即时做出处理文章。
3、本博客的目的是知识交流所用,转载自其它博客或网站,作为自己的参考资料的,感谢这些文章的原创人员