2020.7.6 10:37:00
我们可直接通过Class类获取所有类的成员方法、构造方法等信息,而不是去找到Student类或其他类来得到这些信息。
Java反射机制:是指在运行时去获取一个类的变量和方法信息。然后通过获得到的信息来创建对象,调用方法的一种机制。
由于这种动态性,可以极大的增加程序的灵活性,程序在不用在编译期就完成确定,在运行期仍然可以拓展。
我们要想通过反射去使用一个类,首先我们需要获取到该类的字节码文件的对象,也就是类型为Class类型的对象。
这里我们提供了三种方式来获取Class类的对象:
①新建一个Student类:
package com.hoqis;
/**
* @author HoQis
* @create 2020-07-06 14:30
*/
public class Student {
//成员变量:一个私有、一个默认、一个公共
private String name;
int age;
public String address;
//构造方法,一个私有、一个默认、两个公共
public Student() {
}
private Student(String name){
this.name=name;
}
Student(String name, int age){
this.name = name;
this.age = age;
}
public Student(String name, int age, String address){
this.name = name;
this.age = age;
this.address = address;
}
//成员方法:一个私有、四个公共
private void function(){
System.out.println("function!!!");
}
public void method1(){
System.out.println("method1");
}
public void method2(String s){
System.out.println("method2"+s);
}
public String method3(String s,int i){
return s+","+i;
}
@Override
public String toString() {
return "ReflectClass_Student{" +
"name='" + name + '\'' +
", age=" + age +
", address='" + address + '\'' +
'}';
}
}
②新建一个获取Student类的ReflectDemo类。分别介绍了三种方式来获取Class类对象。
package com.hoqis;
/**
* @author HoQis
* @create 2020-07-06 11:25
*/
/*
三种方式来获取Class对象
1.使用类的class属性来获取该类对应的Class对象
2.调用对象的getClass()方法来获取所属类对应的Class对象
3.使用Class类中的静态方法forName(String className),需传入字符串参数,该参数为某个类的全路径【完整包名】
*/
public class ReflectDemo {
public static void main(String[] args) throws ClassNotFoundException {
//1.使用类的class属性来获取该类对应的Class对象
Class<Student> c1 = Student.class;
System.out.println("使用类的class属性来获取该类对应的Class对象:"+c1);
Class<Student> c2 = Student.class;
System.out.println(c1==c2);
System.out.println("---------------------------");
//2.调用对象的getClass()方法来返回该对象所属类对应的Class对象
Student student = new Student();
Class<? extends Student> c3 = student.getClass();
System.out.println(c1==c3);
System.out.println("---------------------------");
//3.使用Class类中的静态方法forName(String className)
Class<?> c4 = Class.forName("com.hoqis.Student");
System.out.println(c1==c4);
}
}
控制台打印得到的结果为:
使用类的class属性来获取该类对应的Class对象:class com.hoqis.Student
true
---------------------------
true
---------------------------
true
Process finished with exit code 0
【总结】说明这三种方式都能够正常获取到该类对应的Class对象。
Class> c = Class.forName(“com.hoqis.student”);
①使用getConstructors()方法来获取该Class对象表示的类的所有公共的构造函数。 【只能拿到公共的构造函数,其他的不能获取到】
Constructor<?>[] cons = c.getConstructors();//这里获取到是构造函数的数组,故需以下方法进行循环遍历出每一个构造函数
for(Constructor con : cons){
System.out.println(con);
}
②使用getDeclaredConstructors()来获取所有的构造函数。【包含私有的和默认的以及公共的构造函数】
Constructor<?>[] cons = c.getDeclaredConstructors();//这里获取的是构造函数的数组,故需要以下进行循环遍历
for(Constructor con : cons){
System.out.println(con);
}
③ 使用getConstructor()方法来获取一个Constructor对象。该方法提供了一个类的单个构造函数的信息和访问权限。
Constructor<?> con = c.getConstructor();
Object obj = con.newInstance();//使用这个newInstance()方法来创建该类的实例对象,相当于Student s = new Student();
System.out.println(obj);
2020.7.19 13:23:44
接下来我们需要对该Student实体类使用反射来获取到该类中的默认和私有以及公有的成员变量。
只需调用getDeclaredFields()方法即可完成对所有的成员变量进行访问。
反射获取到的三个不同修饰符的成员变量的结果如下图所示:
访问私有的成员变量需要调用setAccessible()方法进行取消访问检查操作,不然系统会报非法异常。
2020.7.19 22:50:18
//1.获取Class对象
Class<?> c = Class.forName("com.hoqis.Student");
//2.获取类成员方法
①getMethods():返回一个包含方法对象的方法,类和接口的所有公共的方法,也包含继承父类的。
Method[] methods = c.getMethods();
for(Method method : methods){
System.out.println(method);
}
②getDeclaredMethods():本类和接口所有声明的方法,不包含继承的方法。
Method[] methods = c.getDeclaredMethods();
for(Method method : methods){
System.out.println(method);
}
//获取单个的方法对象
getMethod()
getDeclaredMethod()
Method m = c.getMethod("method1");
//获取无参构造方法创建对象
Constructor<?> con = c.getConstructor();
Object obj = con.newInstance();
//在类或接口上提供有关单一方法的信息和访问权限 invoke
m.invoke(obj);
获取Class对象
Class<?> c = Class.forName("com.hoqis.Student");
Constructor<?> con = c.getConstructor();
Object obj = con.newInstance();
Method m1 = c.getMethod("method1");
m1.invoke(obj);
Method m2 = c.getMethod("method2",String.class);
m2.invoke(obj,"林青霞");
Method m3 = c.getMethod("method3",String.class,int.class);
Object o = m3.invoke(obj,"林青霞",30);
System.out.println(o);
//调用私有的方法时,需要使用暴力进行访问
Method m4 = c.getDeclaredMethod("function");
m4.setAccessible(true);
m4.invoke(obj)