1.什么是Java反射?
Java的反射(reflection)机制是指在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类的成员变量和方法,可以调用任意一个对象的属性和方法。. 这种动态获取程序信息以及动态调用对象的功能称为Java语言的反射机制。. 反射被视为动态语言的关键。
2.我们为什么要学习java反射?
反射(Reflection) 是 Java 程序开发语言的特征之一,它允许运行中的 Java 程序对自身进行检查,或者说“自审”,并能直接操作程序的内部属性和方法。
3.什么情况能够用到Java反射?
反射是框架设计的灵魂。
在我们平时的项目开发过程中,基本上很少会直接使用到反射机制,但这不能说明反射机制没有用,实际上有很多设计、开发都与反射机制有关,
例如模块化的开发,通过反射去调用对应的字节码;动态代理设计模式也采用了反射机制,还有我们日常使用的 Spring/Hibernate 等框架也大量使用到了反射机制。
举例:①我们在使用JDBC连接数据库时使用Class.forName()通过反射加载数据库的驱动程序;②Spring框架也用到很多反射机制,最经典的就是xml的配置模式。Spring 通过 XML 配置模式装载 Bean 的过程:1) 将程序内所有 XML 或 Properties 配置文件加载入内存中; 2)Java类里面解析xml或properties里面的内容,得到对应实体类的字节码字符串以及相关的属性信息; 3)使用反射机制,根据这个字符串获得某个类的Class实例; 4)动态配置实例的属性。
4.Java反射的利与弊!
1.动态的加载项目,提高代码的灵活性。
2.反射加载类实例要比正常类实例要慢一点。
5. Java反射的基本使用
1.Class类的使用
2.构造方法的反射
3.方法的反射
4.属性的反射
创建一个Student学生类:
package com.zking.FanShe.entity; 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()); } @Override public String toString() { return "Student [sid=" + sid + ", sname=" + sname + ", age=" + age + "]"; } }
6.Class的获取(三种方式)
1.类名.class
Class<Student> cla03 =(Class<Student>)Student.class;
2.对象.getClass()
Student stu = new Student(); Class<Student> cla02 = (Class<Student>)stu.getClass();
3.Class.forName("类路径");
Class<Student> cla01 = (Class<Student>)Class.forName("com.zking.FanShe.entity.Student");
7.获取Class之后就可以进行Java反射动态获取类里面所有内容了。
首先通过Java反射获取构造函数(公有的public,参数类型也要与之对应)
// 获取无参构造函数。
Constructor<Student> c1 = cla01.getConstructor();
Student stu01 = c1.newInstance();//调用newInstance()方法获取一个实例
stu01.setSid("1");
stu01.setSname("zs");
System.out.println(stu01);
//获取有参构造函数(一个)
Constructor<Student> c2 = cla01.getConstructor(String.class);
Student stu02 = c2.newInstance("001");
stu02.setSname("XPW002");
System.out.println(stu02);
//获取有参构造函数(二个)
Constructor<Student> c3 = cla01.getConstructor(String.class,String.class);
Student stu03 = c3.newInstance("002","xpw003");
System.out.println(stu03);
通过Java反射获取构造函数(私有的private,参数类型也要与之对应)
//获取私有的有参构造函数(一个)
Constructor<Student> c4 = cla01.getDeclaredConstructor(Integer.class);
c4.setAccessible(true);//暴力反射获取权限
Student stu04 = c4.newInstance(20);
stu04.setSid("004");
stu04.setSname("xpw04");
System.out.println(stu04);
通过Java反射获取方法(公有的public,参数类型也要与之对应),第一个是参数是方法名,后面接着方法对应的参数
Method met01 = cla01.getMethod("hello");
stu04.setSname("xpwff");
met01.invoke(stu04);
Method met02 = cla01.getMethod("hello", String.class);
met02.invoke(stu04, "ww");
通过Java反射获取方法(私有的private,参数类型也要与之对应),第一个是参数是方法名,后面接着方法对应的参数
Method met03 = cla01.getDeclaredMethod("add", Integer.class,Integer.class);
met03.setAccessible(true);
Integer add = (Integer)met03.invoke(stu04, 1,2);
System.out.println(add);
通过Java反射获取属性(公有的public)参数对应的是属性名称。set方法第一个参数是实例对象。后面是属性值。
Field f1 = cla01.getField("age");
f1.set(stu04, 40);
System.out.println(stu04);
通过Java反射获取属性(私有的private)参数对应的是属性名称。set方法第一个参数是实例对象。后面是属性值。
Field f2 = cla01.getDeclaredField("sname");
f2.setAccessible(true);
f2.set(stu04, "xpw444");
System.out.println(stu04);