1.反射的概念
反射是一种机制,可以在程序运行期间,去调用类中的各种成员。(构造方法,变量,方法)
2.获取字节码对象的三种方式
-
使用对象调用getClass()方法
-
使用类名.class
-
使用Class.forName()静态方法
-
代码演示
public class Demo01获取字节码对象 {
public static void main(String[] args) throws ClassNotFoundException {
//每一个类被加载进内存就会有一个唯一的字节码对象,字节码对象的类型是Class类型
//- 使用对象调用getClass()方法
Class c1 = "abc".getClass();
//- 使用类名.class
Class c2 = String.class;
//- 使用Class.forName()静态方法
//参数里面要写的是类的全类名 包名+类名
Class c3 = Class.forName("java.lang.String");
System.out.println(c1 == c2);//true
System.out.println(c2 == c3);//true
}
}
3.反射操作构造方法
- 反射获取构造方法
- Class类可以调用:
- getConstructor(Class… c) 可以获取某一个构造方法(公共的)
- getConstructors() 可以获取所有的构造方法(公共的)
- Class类可以调用:
public class Demo03反射操作构造方法 {
public static void main(String[] args) throws Exception {
//获取类的字节码对象
Class c = Class.forName("com.demo.Student");
//获取构造方法
//getConstructor(Class... c) :获取某一个构造方法
//()什么都不写代表获取空参构造
Constructor con = c.getConstructor();
System.out.println(con);
//()写参数可以获取有参构造
Constructor con2 = c.getConstructor(String.class, int.class);
System.out.println(con2);
//getConstructors() :获取所有的公共的构造方法
Constructor[] cons = c.getConstructors();
//打印数组
System.out.println(Arrays.toString(cons));
}
}
-
反射执行构造方法
-
Constructor类可以调用:
-
newInstance(Object… obj) : 执行当前构造方法创建对象。
Object… obj 表示的是创建对象时的实际参数。
-
-
public class Demo04构造方法的执行 {
public static void main(String[] args) throws Exception {
//获取类的字节码对象
Class c = Class.forName("com.demo.Student");
//getConstructor(Class... c) :获取某一个构造方法
//()什么都不写代表获取空参构造
Constructor con = c.getConstructor();
//执行构造方法,可以真正创建出对象
//newInstance(Object... obj) :让构造方法执行
Student s1 = (Student) con.newInstance();
System.out.println(s1);
//()写参数可以获取有参构造
Constructor con2 = c.getConstructor(String.class, int.class);
//执行这个有参构造,创建对象
//参数Object... obj 代表的是构造方法的实际参数
Student s2 = (Student) con2.newInstance("柳岩", 36);
System.out.println(s2);
}
}
4.反射操作成员方法
-
反射获取成员方法
-
Class类中的方法:
-
getMethod(String name, Class… c) :获取一个成员方法(公共的)
String name 表示方法名称
Class… c 表示的是方法的参数的类型
-
getMethods() : 获取类中的所有方法(公共的)
-
-
public class Demo01反射获取成员方法 {
public static void main(String[] args) throws Exception {
//获取字节码对象
Class c = Class.forName("com.demo.Student");
//获取类中的成员方法
//getMethod(String name,Class... c) :获取某一个成员方法(公共的)
//获取睡觉的方法
Method m1 = c.getMethod("sleep");
System.out.println(m1);
//获取吃饭方法
Method m2 = c.getMethod("eat", String.class);
System.out.println(m2);
//getMethods() :获取所有的成员方法(公共的)
Method[] methods = c.getMethods();
//打印数组
System.out.println(Arrays.toString(methods));
}
}
-
反射执行成员方法
-
Method类可以调用:
-
Object invoke(Object obj , Object… o) :让方法执行
第一个参数表示执行的对象
第二个参数表示方法的实际参数
返回值表示方法的实际返回值
-
-
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
public class Demo02反射执行成员方法 {
public static void main(String[] args) throws Exception {
//获取字节码对象
Class c = Class.forName("com.demo.Student");
//创建对象
Constructor con = c.getConstructor();
Student stu = (Student) con.newInstance();
//获取睡觉的方法
Method m1 = c.getMethod("sleep");
// invoke(Object obj,Object... parm): obj表示要执行方法的对象 parm表示的是执行方法的实际参数
//执行睡觉方法
m1.invoke(stu);
//获取吃饭方法
Method m2 = c.getMethod("eat", String.class);
//执行吃饭方法
m2.invoke(stu, "玉米");
}
}
5.暴力反射
上面反射获取内容时,只能获取公共的内容,可以使用暴力反射获取任意的内容;
在使用反射的时候,有加了Declared的方法,这些方法都叫做暴力反射
在暴力反射获取到内容之后,需要调用 setAccessable(true)设置权限true表示允许使用
public class Demo03暴力反射 {
public static void main(String[] args) throws Exception {
//获取字节码对象
Class c = Class.forName("com.demo.Student");
//获取构造方法
//暴力反射 就是在方法中间加一个词Declared,就可以获取任意权限的内容
Constructor con = c.getDeclaredConstructor();
System.out.println(con);
//设置权限
con.setAccessible(true);
//创建对象
Student s = (Student) con.newInstance();
System.out.println(s);
//----------------------------------------
//暴力反射获取方法
Method m = c.getDeclaredMethod("study");
//设置权限
m.setAccessible(true);
//执行学习的方法
m.invoke(s);
}
}