反射技术其实就是动态加载一个指定的类,并获取该类中的所有内容。而且将字节码文件封装成对象,并将字节码文件中的内容都封装成对象,这样便于操作这些成员,简单来说:反射技术可以对一个类进行解剖,反射大大增强了应用程序的可扩展性。
反射技术的原理如下图所示:
但是要想要对字节码文件进行解剖,必须要有字节码文件对象. 如何获取字节码文件对象呢?
要读取的类文件源码:
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 classz=p.getClass();4 System.out.println(classz);5 Person p1=new Person();6 Class 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 }
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 }
本文为博主原创文章,转载请注明出处:
1、本博客的原创原创文章,都是本人平时学习所做的笔记,如有错误,欢迎指正。2、如有侵犯您的知识产权和版权问题,请通知本人,本人会即时做出处理文章。3、本博客的目的是知识交流所用,转载自其它博客或网站,作为自己的参考资料的,感谢这些文章的原创人员