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<T> 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<T> 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基础的重点知识点全集》