动态获取类信息以及动态调用该对象的属性和方法的功能称之为反射。
此处的动态指的是运行时获取,javac编译 -> 生成.class文件 -> 运行主类
优点:
缺点:
实现反射操作需要4个核心类,这些类都在java.lang.reflect包下
1.在Java中获取一个类的class对象,有三种途径:
// Ⅰ.直接通过类名.class获取class对象
Class cls1 = Student.class;
// Ⅱ.通过该类的任意实例化对象,调用getClass()方法
Class cls2 = new Student().getClass();
// Ⅲ.使用Class类提供的静态方法 Class.forName(“包名.类名”);
Class cls3 = Class.forName("demo.Student");
2.调用 class对象 的newInstance()方法产生 Student类 的实例
// 默认调用该类的无参构造,当访问不到无参构造时,无法使用该方法
Student stu = (Student) cls.newInstance();
1.通过class 对象获取构造方法
① getConstructors() 只能获取当前类的 所有public 权限的构造方法
Constructor[] constructors = cls.getConstructors();
[public reflect.Student(java.lang.String,int,java.lang.String),
public reflect.Student()]
② getDeclaredConstructors() 能获取当前类的所有权限的构造方法
Constructor[] constructors1 = cls.getDeclaredConstructors();
[public reflect.Student(java.lang.String,int,java.lang.String), reflect.Student(java.lang.String,int),
private reflect.Student(java.lang.String),
public reflect.Student()]
③ 拿到一个无参构造的constructor对象
Constructor constructor = cls.getDeclaredConstructor();
④ 拿到一个有参构造的constructor对象
Constructor constructor1 = cls.getDeclaredConstructor(String.class);
Constructor constructor2 = cls.getDeclaredConstructor(String.class, Integer.class);
Constructor constructor3 = cls.getDeclaredConstructor(String.class, Integer.class, String.class);
2.当拿到特定的Constructor对象时,就可以通过该对象来实例化Student对象
// 破坏封装,仅限当前JVM进程中的这个constructor1可用
constructor1.setAccessible(true);
Student stu = (Student) constructor1.newInstance();
① 获取该类的所有方法Method对象,可以拿到当前类以及其父类的所有public权限的方法
Method[] methods = cls.getMethods();
② 可以拿到当前类的所有权限的方法,包括private权限
Method[] methods1 = cls.getDeclaredMethods();
③ 拿到当前类的某个方法,getDeclaredMethod(方法名称,方法的参数类型)
Method staticMethod = cls.getDeclaredMethod("staticFunc", String.class);
① 可以拿到当前类以及其父类的所有public的属性
Field[] fields = cls.getFields();
② 可以拿到当前类的所有权限的属性,包括private权限
Field[] fields1 = cls.getDeclaredFields();
③ 可以拿到指定属性
Field field = cls.getDeclaredField("name");
// 第一步,获取 class 对象
Class cls = new Demo().getClass();
// cls.getDeclaredMethod(方法名称,方法的参数类型)
Method staticMethod = cls.getDeclaredMethod("staticFunc", String.class);
// 静态方法的调用不需要实例化对象
// methodFunc.invoke(具体对象,方法参数);
staticMethod.invoke(null, "abcde");
Method methodFunc = cls.getDeclaredMethod("fun");
// fun()方法是private的,需要破坏封装
methodFunc.setAccessible(true);
// fun()是成员方法,必须通过Student的对象来调用
Student stu = (Student) cls.newInstance();
// 开始调用方法
// methodFunc.invoke(具体对象,方法参数);
methodFunc.invoke(stu);
通过反射来调用一个类的方法的过程:
// 第一步,获取 class 对象
Class cls = Class.forname("demo.Student");
// 获取指定的属性
Field field = cls.getDeclaredField("name");
field.setAccessible(true); // 因为name是private修饰的属性
// name是成员属性,所以需要Student的实例化对象
Student stu = (Student) cls.newInstance();
// 设置属性值:set(具体对象, 属性值);
field.set(stu, "张三");
// 获取属性值:通过具体的Student对象获取name属性
System.out.println(field.get(stu));
通过反射来获取一个类的属性的过程:
总结:
提示:这里对文章进行总结:
以上就是今天的学习内容,本文是Java反射的学习,认识什么是反射,反射相关的类,以及反射的原理和过程。之后的学习内容将持续更新!!!