什么是反射?
反射(Reflection)是指在程序运行时,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法。反射机制可以使Java程序具有更强的动态性和扩展性,使Java程序更具有灵活性和智能化。
Java反射机制主要涉及到以下几个类:
Class类:反射的核心类,用于获取类的各种信息,比如类名、构造方法、成员变量、成员方法等。
Constructor类:用于描述类的构造方法。
Method类:用于描述类的成员方法。
Field类:用于描述类的成员变量。
通过反射,我们可以在程序运行时动态地创建对象、调用方法和访问属性,实现一些动态性较强的操作,比如动态代理、动态加载类、动态修改类等。反射机制是Java语言与其他动态语言的桥梁,也是Java框架中很重要的一部分。
反射的作用
Java反射机制的作用如下:
运行时获取对象信息:通过反射,我们可以在运行时获取类的相关信息,比如类名、构造方法、成员变量、成员方法等,这对于某些框架、工具或者动态语言来说是非常有用的。
动态创建对象:通过反射,我们可以在运行时根据类名动态地创建对象。这使得我们可以更灵活地设计程序,比如根据配置文件中的类名动态创建对象。
动态调用方法:通过反射,我们可以在运行时动态调用对象的方法。这使得我们可以根据实际需要来动态选择需要调用的方法,而不是在编写代码时就静态固定下来了。
动态访问属性:通过反射,我们可以在运行时动态访问对象的属性。这使得我们可以更加灵活地设计程序,比如根据用户的输入来动态访问对象的属性。
安全性检查:反射机制虽然很强大,但是使用不当也会产生安全问题。因此,反射机制也可以用于安全性检查,比如检查用户输入的类名是否合法。
总之,Java反射机制可以使Java程序更加灵活,更具有动态性和可扩展性,为Java框架的设计和实现提供了重要的支持和工具。
为什么要用反射?
Java Reflection功能非常强大,并且非常有用,比如:
获取任意类的名称、package信息、所有属性、方法、注解、类型、类加载器等
获取任意对象的属性,并且能改变对象的属性
调用任意对象的方法
判断任意一个对象所属的类
实例化任意一个类的对象
通过反射我们可以实现动态装配,降低代码的耦合度,动态代理等。
一.反射的应用
1.1类类的获取方式
package com.liaozhixiang.fs; /** * 类类的获取方式:一切的反射操作都是从获取类对象开始 * 1.Class.forName * 2.类实例.getClass * 3.类名.class * * * @author Administrator * */ public class Deom1 { public static void main(String[] args) throws Exception { Student st = new Student(); //应用在jdbc数据库连接 Class.forName System.out.println("通过Class.forName结果如下"); Class c = Class.forName("com.liaozhixiang.fs.Student"); System.out.println(c); System.out.println(); //类实例.getClass 可以编写通用的增删改 System.out.println("通过类实例.getClass结果如下"); Class c2 = st.getClass(); System.out.println(c2); System.out.println(); System.out.println("通过类类名.class结果如下"); Class c3 = Student.class; System.out.println(c3); } }
运行结果:
注意:一切的反射操作都是从获取类对象开始
1.2反射实例化
package com.liaozhixiang.fs; import java.lang.reflect.Constructor; /** * 反射实例化 * * @author Administrator * * * * */ public class Deom2 { public static void main(String[] args) throws Exception { Student st = new Student(); Class<Student> c1 = Student.class; //调用无参构造反射实例化 Object ob = c1.newInstance(); System.out.println(ob); System.out.println(); //调用带一个参数的构造反射实例化 Constructor<Student> ct1 = c1.getConstructor(String.class); Student student1 = ct1.newInstance("1433"); System.out.println(student1); System.out.println(); //调用带二个参数的构造反射实例化 Constructor<Student> ct2 = c1.getConstructor(String.class,String.class); Student student2 = ct2.newInstance("1433","哈士奇"); System.out.println(student2); System.out.println(); //调用Student类私有的构造反射实例化 Constructor<Student> ct3 = c1.getDeclaredConstructor(Integer.class); //打开获取私有化访问权限 ct3.setAccessible(true); Student student3 = ct3.newInstance(66); System.out.println(student3); } }
运行结果:
1.3 反射方法的调用
package com.liaozhixiang.fs; import java.lang.reflect.Method; /** * 反射方法调用 * @author Administrator * */ public class Deom3 { public static void main(String[] args) throws Exception { Class c = Student.class; Student st = (Student) c.newInstance(); // 反射方法调用 无参数方法,需要先获取到方法对象 Method m1 = c.getMethod("hello"); // invoke(?,?) 类实例 参数 Object invoke1 = m1.invoke(st); System.out.println(invoke1); System.out.println(); // 反射方法调用有参数方法 Method m2 = c.getMethod("hello", String.class); Object invoke2 = m2.invoke(st, "lzx"); System.out.println(invoke2); System.out.println(); // 反射方法调用私有化有参数构造方法 Method m3 = c.getDeclaredMethod("add",Integer.class,Integer.class); m3.setAccessible(true); Object invoke3 = m3.invoke(st, 1,2); System.out.println(invoke3); } }
运行结果结果:
1.4反射读写属性
package com.liaozhixiang.fs; import java.lang.reflect.Field; /** * 反射读写属性 * @author Administrator * */ public class Deom4 { public static void main(String[] args) throws Exception, SecurityException { Class c = Student.class; Student stu = new Student("s1", "lzx"); System.out.println(stu.getSid()); System.out.println(stu.getSname()); System.out.println(); // 反射存值 Field sname = c.getDeclaredField("sname"); sname.setAccessible(true); sname.set(stu, "获取"); //反射获取属性值 Field[] fields = c.getDeclaredFields(); for (Field field : fields) { field.setAccessible(true); System.out.println(field.getName()+":"+field.get(stu)); } } }
运行结果: