反射,是指通过对象反过来获取类的属性、构造方法、普通方法的机制。
一、获取类信息
(一)通过类名获取
public class Student {
//属性
public Integer id;
public String name;
private String hobby;
public String school="Perking University";
//构造方法1
public Student(Integer id, String name) {
this.id = id;
this.name = name;
}
//构造方法2
private Student(Integer id) {
this.id = id;
}
public static void main(String[] args) throws Exception {
Class clazz1=Student.class;
System.out.println(clazz1);
}
}
(二)通过对象获取
public class Student {
//属性
public Integer id;
public String name;
private String hobby;
public String school="Perking University";
//构造方法1
public Student(Integer id, String name) {
this.id = id;
this.name = name;
}
//构造方法2
private Student(Integer id) {
this.id = id;
}
public static void main(String[] args) throws Exception {
Student st=new Student(1001,"Tom");
Class clazz1=st.getClass();
System.out.println(clazz1);
}
}
(三)通过路径获取
public class Student {
//属性
public Integer id;
public String name;
private String hobby;
public String school="Perking University";
//构造方法1
public Student(Integer id, String name) {
this.id = id;
this.name = name;
}
//构造方法2
private Student(Integer id) {
this.id = id;
}
public static void main(String[] args) throws Exception {
Class clazz1=Class.forName("com.test.Student");
System.out.println(clazz1);
}
}
以上三种方法中,Class 类是所有类的类,其内部的对象为各种类。
二、获取属性
属性的获取是在类信息的基础上完成的,Field 类是属性类,内部对象为各种各样的属性。根据属性是公共属性还是私有属性,可以用四种方法完成获取:
public class Student {
//属性
public Integer id;
public String name;
private String hobby;
public String school="Perking University";
//构造方法1
public Student(Integer id, String name) {
this.id = id;
this.name = name;
}
//构造方法2
private Student(Integer id) {
this.id = id;
}
public static void main(String[] args) throws Exception {
Class clazz1=Student.class;
//① 获取公共属性,不包括private属性
Field[] fie1=clazz1.getFields();
for(Field x:fie1) {System.out.println(x);}
//② 获取所有属性,包括private属性
Field[] fie2=clazz1.getDeclaredFields();
for(Field x:fie2) {System.out.println(x);}
//③ 获取指定公共属性
Field fie3=clazz1.getField("id");
System.out.println(fie3);
//④ 获取指定属性
Field fie4=clazz1.getDeclaredField("hobby");
System.out.println(fie4);
}
}
三、获取构造方法
构造方法的获取同样是在类信息的基础上完成的,Constructor 类是构造方法类,内部对象为各种各样的构造方法。根据构造方法是 public 还是 private ,可以用四种方法完成获取:
public class Student {
//属性
public Integer id;
public String name;
private String hobby;
public String school="Perking University";
//构造方法1
public Student(Integer id, String name) {
this.id = id;
this.name = name;
}
//构造方法2
private Student(Integer id) {
this.id = id;
}
public static void main(String[] args) throws Exception {
Class clazz1=Student.class;
//① 获取public构造方法
Constructor[] con1=clazz1.getConstructors();
for(Constructor x:con1) {System.out.println(x);}
//② 获取所有构造方法
Constructor[] con2=clazz1.getDeclaredConstructors();
for(Constructor x:con2) {System.out.println(x);}
//③ 获取指定public构造方法
Constructor con3=clazz1.getConstructor(Integer.class,String.class);
System.out.println(con3);
//④ 获取指定构造方法
Constructor con4=clazz1.getDeclaredConstructor(Integer.class);
System.out.println(con4);
}
}
获取指定构造方法的参数不能是基本类型,而只能是包装类,所以用 Integer,而不用 int。
四、获取普通方法
普通方法的获取也是在类信息的基础上完成的,Method 类是方法类,内部对象为各种各样的方法。根据方法是 public 还是 private 或继承自父类的方法,可以用四种方法完成获取:
public class Student {
//属性
public Integer id;
public String name;
private String hobby;
public String school="Perking University";
//构造方法1
public Student(Integer id, String name) {
this.id = id;
this.name = name;
}
//构造方法2
private Student(Integer id) {
this.id = id;
}
//普通方法1
public void run1()
{
System.out.println("run1");
}
//普通方法2
private String run2(String name)
{
this.name=name;
return this.name;
}
public static void main(String[] args) throws Exception {
Class clazz1=Student.class;
//① 获取public方法,与继承自父类的方法
Method[] met1=clazz1.getMethods();
for(Method x:met1) {System.out.println(x);}
//② 获取public方法,与private方法
Method[] met2=clazz1.getDeclaredMethods();
for(Method x:met2) {System.out.println(x);}
//③ 获取指定public方法或继承自父类的方法
Method met3=clazz1.getMethod("run1", null);
System.out.println(met3);
//④ 获取指定public方法或private方法
Method met4=clazz1.getDeclaredMethod("run2", String.class);
System.out.println(met4);
}
}
五、调用方法
(一)调用构造方法
调用构造方法,使用获取到的指定构造方法的 .newInstance() 方法,括号里面写入构造方法的实例化参数:
public class Student {
//属性
public Integer id;
public String name;
private String hobby;
public String school="Perking University";
//构造方法1
public Student(Integer id, String name) {
this.id = id;
this.name = name;
}
//构造方法2
private Student(Integer id) {
this.id = id;
}
//普通方法1
public void run1()
{
System.out.println("run1");
}
//普通方法2
private String run2(String name)
{
this.name=name;
return this.name;
}
public static void main(String[] args) throws Exception {
Class clazz1=Student.class;
//调用构造方法
Constructor con=clazz1.getDeclaredConstructor(Integer.class,String.class);
Student stu=(Student) con.newInstance(1001,"Tom");
}
}
(二)调用普通方法
调用普通方法,需要先创建实例化对象,也就是调用构造方法。然后使用获取到的指定普通方法的 .invoke() 方法去调用该普通方法,括号内写入要使用该普通方法的实例化对象,与该普通方法的参数:
public class Student {
//属性
public Integer id;
public String name;
private String hobby;
public String school="Perking University";
//构造方法1
public Student(Integer id, String name) {
this.id = id;
this.name = name;
}
//构造方法2
private Student(Integer id) {
this.id = id;
}
//普通方法1
public void run1()
{
System.out.println("run1");
}
//普通方法2
private String run2(String name)
{
this.name=name;
return this.name;
}
public static void main(String[] args) throws Exception {
Class clazz1=Student.class;
//调用构造方法
Constructor con=clazz1.getDeclaredConstructor(Integer.class,String.class);
Student stu=(Student) con.newInstance(1001,"Tom");
//调用普通方法
Method met1=clazz1.getDeclaredMethod("run1", null);
met1.invoke(stu, null);
}
}