1.什么是反射机制
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.
总结就是:反射就是把java类中的各种成分映射成一个个的Java对象
2.反射的作用
1.运行时动态获取类的信息:在编写代码时,对于类的信息是必须在编译时确定的,但在运行时,有时需要根据某些条件,动态获取某个类的信息,这时就可以使用Java中的反射机制。
2.动态生成对象:反射机制可以在运行时生成对象,这样就可以根据参数的不同,动态的创建不同的类的实例对象。
3.动态调用方法:通过反射机制可以调用类中的方法,不论这些方法是否是公共的,也不论这些方法的参数个数和类型是什么,反射机制都具有这样的能力。
4.动态修改属性:利用反射机制可以获取到类中的所有成员变量,并可以对其进行修改。
5.实现动态代理:利用反射机制可以实现代理模式,通过代理对象完成原对象对某些方法的调用,同时也可以在这些方法的调用前后做一些额外的处理。
3.反射应用
首相我们先实例化一个student
package com.zking.xzs; /** * 学生实体 * @author biao * */ public class Student { private String sid; private String sname; public Integer age; static{ System.out.println("加载进jvm中!"); } public Student() { super(); System.out.println("调用无参构造方法创建了一个学生对象"); } public Student(String sid) { super(); this.sid = sid; System.out.println("调用带一个参数的构造方法创建了一个学生对象"); } public Student(String sid, String sname) { super(); this.sid = sid; this.sname = sname; System.out.println("调用带二个参数的构造方法创建了一个学生对象"); } @SuppressWarnings("unused") private Student(Integer age) { System.out.println("调用Student类私有的构造方法创建一个学生对象"); this.age = age; } public String getSid() { return sid; } public void setSid(String sid) { this.sid = sid; } public String getSname() { return sname; } public void setSname(String sname) { this.sname = sname; } public void hello() { System.out.println("你好!我是" + this.sname); } public void hello(String name) { System.out.println(name + "你好!我是" + this.sname); } @SuppressWarnings("unused") private Integer add(Integer a, Integer b) { return new Integer(a.intValue() + b.intValue()); } }
3.1如何拿到这个class
拿到Class方法有三种:
1.Class.forname--应用在jdbc数据库连接中
2.类实例.getclass()---通用增删改
3.类名.class--通用查询
如:
package com.zking.xzs; /** * 类类的获取方式 * 一切反射的操作都是从类对象开始 * @author biao * */ public class Demo1 { public static void main(String[] args) throws Exception { //1.Class.forname--应用在jdbc数据库连接中 Class<?> forName = Class.forName("com.ctb.reflect.Student"); System.out.println(forName); Student stu=new Student(); //2.类实例.getclass()---通用增删改 Class<? extends Student> class1 = stu.getClass(); System.out.println(class1); //3.类名.class--通用查询 Class<Student> class2 = Student.class; System.out.println(class2); } }
4.反射实例化
对象.newInstance()
这里:newInstance()方法内部实际上调用了无参数构造方法,必须保证无参构造存在才可以。
否则会抛出java.lang.InstantiationException
异常。
package com.zking.xzs; import java.lang.reflect.Constructor; /** * 反射实例化 * 添加有参构造器,一定要补一个无参构造器 * @author biao * */ public class Demo2 { public static void main(String[] args) throws Exception { //一切反射从类类开始 Class<Student> c1=Student.class; Student stu=new Student(); //调用无参构造器反射实例化 Object o=c1.newInstance(); System.out.println(o); //调用1个参数的构造器反射实例化 Constructor<Student> ct = c1.getConstructor(String.class); Student student = ct.newInstance("5869"); System.out.println(student); //调用2个参数的构造器反射实例化 Constructor<Student> ct1 = c1.getConstructor(String.class,String.class); Student s2 = ct1.newInstance("66", "宁波"); System.out.println(s2); //getConstructor方法只能获取到公有的构造器对象 //调用私有化的构造器反射实例化 Constructor<Student> ct2 = c1.getDeclaredConstructor(Integer.class); //打开私有修饰的访问权限 ct2.setAccessible(true); Student ss = ct2.newInstance(89); System.out.println(ss); } }
5.反射实例化的方法调用
如:Method类方法
package com.zking.xzs; import java.lang.xzs.Method; /** * 反射动态方法调用 * @author biao * */ public class Demo3 { public static void main(String[] args) throws Exception { Student stu = new Student(); Class c = stu.getClass(); //反射的无参数方法调用 //getMethod(?,?)方法名,调用方法要传参数类型 Method m1 = c.getMethod("66"); //invoke(?,?)类实例,参数值 Object invoke = m1.invoke(stu); System.out.println(invoke); //反射的有参数方法调用 Method m2 = c.getMethod("学生", String.class); System.out.println(m2.invoke(stu, "幺妹")); //反射的私有化有参数方法调用 Method m3 = c.getDeclaredMethod("add", Integer.class, Integer.class); m3.setAccessible(true); System.out.println(m3.invoke(stu, 90, 10)); } }
6.反射读写属性
package com.zking.xzs; import java.lang.xzs.Field; /** * 反射读写属性 * * @author biao * */ public class Demo4 { public static void main(String[] args) throws Exception { Student stu = new Student("12324", "幺妹"); stu.age = 3040; Class clz = stu.getClass(); //获取stu实例对象中的所有属性值 //反射存值 Field sname = clz.getDeclaredField("sname"); sname.setAccessible(true); sname.set(stu, "现在是"); //反射获取属性值 Field[] fields = clz.getDeclaredFields(); for (Field field : fields) { field.setAccessible(true); System.out.println(field.getName() + ":" + field.get(stu)); } } }
总之:
在java框架开发中使用反射机制可以提供更灵活、可扩展的特性。