1、概念:
反射机制:是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意属性和方法;这种动态获取信息以及动态调用对象方法的功能称为 java 语言的反射机制;
他的工作原理是这样的:当一个字节码文件加载到内存的时候, jvm会对该字节码进行解剖,然后创建一个对象的Class对象,jvm把字节码文件的信息全部都存储到该Class对象中,我们只要获取到Class对象,我们就可以使用该对象设置对象的属性或者调用对象的方法等操作。
2、获取Class类对象的三种方式
* 类名.class属性
* 对象名.getClass()方法
* Class.forName(全类名)方法
3、原理图:
4、案例:获得Class类
class ReflectDemo {
public static void main(String[] args) throws ClassNotFoundException {
// 1.Class类中的静态方法forName("全类名")
//全类名:包名 - 类名
Class clazz1 = Class.forName("com.bean.Student");
System.out.println(clazz1);
// 2.通过class属性来获取
Class clazz2 = Student.class;
System.out.println(clazz2);
// 3.利用对象的getClass方法来获取class对象
// getClass方法是定义在Object类中.
Student s = new Student();
Class clazz3 = s.getClass();
System.out.println(clazz3);
System.out.println(clazz1 == clazz2);
System.out.println(clazz2 == clazz3);
}
}
5、获得构造方法,还可以获得成员属性Field、成员方法Method等这些,获得私有的时用带上Declared的方法,例如:getDeclaredConstructor
public class Student {
private String name;
private int age;
// 私有的有参构造方法
private Student(String name) {
System.out.println("name的值为:" + name);
System.out.println("private...Student的有参构造方法");
}
// 公共的无参构造方法
public Student() {
System.out.println("public...Student的无参构造方法");
}
// 公共的有参构造方法
public Student(String name, int age) {
System.out.println("name的值为:" + name + "age的值为:" + age);
System.out.println("public...Student的有参构造方法");
}
}
class ReflectDemo {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
System.out.println("获取所有公共构造方法对象的数组===========");
method1();
System.out.println("获取单个构造方法对象===========");
method2();
System.out.println("获取所有构造方法对象的数组===========");
method3();
System.out.println("获取单个构造方法对象===========");
method4();
}
private static void method4() throws ClassNotFoundException, NoSuchMethodException {
// Constructor getDeclaredConstructor(Class... parameterTypes):
//返回单个构造方法对象
//1.获取Class对象
Class clazz = Class.forName("com.bean.Student");
System.out.println("String+int的构造");
Constructor constructor = clazz.getDeclaredConstructor(String.class,int.class);
System.out.println(constructor);
System.out.println("String的构造");
constructor=clazz.getDeclaredConstructor(String.class);
System.out.println(constructor);
}
private static void method3() throws ClassNotFoundException, NoSuchMethodException {
//Constructor getConstructor(Class... parameterTypes):
// 返回单个公共构造方法对象
//1.获取Class对象
Class clazz = Class.forName("com.bean.Student");
//小括号中,一定要跟构造方法的形参保持一致.
Constructor constructor1 = clazz.getConstructor();
System.out.println(constructor1);
Constructor constructor2 = clazz.getConstructor(String.class, int.class);
System.out.println(constructor2);
//因为Student类中,没有只有一个int的构造,所以这里会报错.
// Constructor constructor3 = clazz.getConstructor(int.class);
// System.out.println(constructor3);
}
private static void method2() throws ClassNotFoundException {
//返回所有构造方法对象的数组
//1.获取Class对象
Class clazz = Class.forName("com.bean.Student");
Constructor[] constructors = clazz.getDeclaredConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
}
private static void method1() throws ClassNotFoundException {
//返回所有公共构造方法对象的数组
//1.获取Class对象
Class clazz = Class.forName("com.bean.Student");
Constructor[] constructors = clazz.getConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
}
}
6、通过构造方法创建对象
方法名 | 说明 |
---|---|
T newInstance(Object…initargs) | 根据指定的构造方法创建对象 |
setAccessible(boolean flag) | 设置为true,表示取消访问检查 |
// T newInstance(Object... initargs):根据指定的构造方法创建对象
class ReflectDemo2 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
method1();
method2();
method3();
method4();
}
private static void method4() throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
//获取一个私有的构造方法并创建对象
//1.获取class对象
Class clazz = Class.forName("com.fanshe.Student");
//2.获取一个私有化的构造方法.
Constructor constructor = clazz.getDeclaredConstructor(String.class);
//被private修饰的成员,不能直接使用的
//如果用反射强行获取并使用,需要临时取消访问检查
constructor.setAccessible(true);
//3.直接创建对象
Student student = (Student) constructor.newInstance("zhangsan");
System.out.println(student);
}
private static void method3() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
//简写格式
//1.获取class对象
Class clazz = Class.forName("com.bean.Student");
//2.在Class类中,有一个newInstance方法,可以利用空参直接创建一个对象
Student student = (Student) clazz.newInstance();//这个方法现在已经过时了,了解一下
System.out.println(student);
}
private static void method2() throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
//1.获取class对象
Class clazz = Class.forName("com.fanshe.Student");
//2.获取构造方法对象
Constructor constructor = clazz.getConstructor();
//3.利用空参来创建Student的对象
Student student = (Student) constructor.newInstance();
System.out.println(student);
}
private static void method1() throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException, InvocationTargetException {
//1.获取class对象
Class clazz = Class.forName("com.bean.Student");
//2.获取构造方法对象
Constructor constructor = clazz.getConstructor(String.class, int.class);
//3.利用newInstance创建Student的对象
Student student = (Student) constructor.newInstance("杨天真", 22);
System.out.println(student);
}
}
7、反射和new 的区别
1)、new的对象无法访问其中的私有属性,反射出来的可以通过设置setAccessible()方法来省略访问权限符;
2)、new必须要知道类名,而反射创建对象不需要知道类型也可以创建;
本电子书目录:《Java基础的重点知识点全集》