一丶基本概述
类的反射是非常重要的一个知识点,许多框架都是依赖这个技术。所谓的反射就是在运行状态中通过类就可以获取类中的所有构造方法,变量以及方法(包括静态,以及私有都可以)。
实际上,我们创建的每一个类也都是对象,都是java.lang.Class的对象。既然是类的反射那么类Class就是其中的重点了,下面来介绍一下Class。
在网上看到一张关于类加载的图片,非常形象大家可以参考一下
二丶反射的具体使用
假设现在有一个实体类Student
package reflect;
public class Student {
public static int age ;
private String name;
protected int no;
String hobby;
public Student(int no){
this.no = no;
}
protected Student(int no,String name){
this.name = name;
this.no = no;
}
private Student(String name){
this.name = name;
this.no = no;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getHobby() {
return hobby;
}
public void setHobby(String hobby) {
this.hobby = hobby;
}
public void sayHi(String name){
System.out.println(name + "sayHi");
}
private void sayGoodbye(String name){
System.out.println(name + "sayGoodbye");
}
@Override
public String toString() {
return "Student{" +
"age=" + age +
", name='" + name + '\'' +
", no=" + no +
", hobby='" + hobby + '\'' +
'}';
}
}
获取类对象的方法有三种
Class cls1 = Student.class;
Class cls2 = Class.forName("reflect.Student");
Student stu = new Student();
Class cls3 = stu.getClass();
//可以验证Class对象只创建一次
System.out.println(cls1 == cls2);
System.out.println(cls1 == cls3);
获取构造方法
public static void getConstrucor() throws Exception{
Class cls = Student.class;
//获取所有公有的构造
Constructor[] cons = cls.getConstructors();
for(Constructor con : cons){
System.out.println(con);
}
//获取所有构造
Constructor[] deCons = cls.getDeclaredConstructors();
for(Constructor con : deCons){
System.out.println(con);
}
//获取指定参数类型的公有构造
Constructor con1 = cls.getConstructor(int.class);
//通过构造方法创造一个Student对象
Student obj1 = (Student)con1.newInstance(3);
System.out.println(obj1.toString());
//获取指定类型参数的构造(无视修饰符)
Constructor con2 = cls.getDeclaredConstructor(String.class);
//破解私有的权限,不加报错
con2.setAccessible(true);
//通过构造方法创造一个Student对象
Student obj2 = (Student)con2.newInstance("张三");
System.out.println(obj2.toString());
}
获取成员变量
public static void getField() throws Exception {
Class cls = Student.class;
//获取所有成员变量包括
Field[] fields1 = cls.getDeclaredFields();
for(Field f : fields1){
System.out.println(f);
}
System.out.println("--------------");
//只能获取公有的成员变量
Field[] fields2 = cls.getFields();
for(Field f : fields2){
System.out.println(f);
}
System.out.println("--------------");
Student stu = new Student();
//给成员变量赋值,其实和构造方法没什么差别。
// 参数是成员变量名
Field f1 = cls.getDeclaredField("name");
//私有需要破解权限
f1.setAccessible(true);
//需要传入一个对象来设置
f1.set(stu,"张三");
System.out.println(stu.toString());
Student stu2 = new Student();
Field f2 = cls.getField("age");
f2.set(stu2,21);
System.out.println(stu2.toString());
}
成员方法的调用
public static void getMethod() throws Exception{
Class cls = Student.class;
//获取所有方法,包括构造方法
Method[] methods = cls.getDeclaredMethods();
for(Method m : methods){
System.out.println(m);
}
System.out.println("----------------------");
//和之前大同小异,但是这个会获取到父类的所有公有方法
Method[] methods2 = cls.getMethods();
for(Method m : methods2){
System.out.println(m);
}
//获取方法时候和之前不同的就是需要传入两个参数一个是方法名,一个是参数类型
Method m = cls.getMethod("sayHi", String.class);
//调用方法需要传入对象以及方法参数
//通过无参构造方法新建一个对象
m.invoke(cls.getConstructor(null).newInstance(),"张三");
}
}
以上就是简单的一些反射知识,有了反射我们可以通过配置文件传入类名,然后用Class.forName()来获取类对象,对于一些特地的场景非常的实用