黑马程序员技术交流社区

标题: 【成都校区】java 反射 [打印本页]

作者: 小刀葛小伦    时间: 2020-3-6 12:56
标题: 【成都校区】java 反射
java 反射
1. java 反射机制的概念
在java运行状态中,对于任意一个实体类,都能够知道这个类的所有属性和方法 ;对应任何一个对象,都能调用它的任意方法和属性。这种动态获取信息以及动态调用对象方法的功能成为java反射机制。
2. java 文件和 .class 文件的关系
java 文件
java文件中包含代码的所有内容,类,接口,成员变量,成员方法....
.class 字节码文件
.class 是由 java文件 通过 javac 编译成对应的 .class文件。在.class 字节码文件中包含了  java 文件的所有内容。
3. 程序加载过程和.class文件的关系
在Java文件运行过程中,当前程序需要哪一个类参与代码执行,那么就需要加载这个类的.class字节码文件,该.class字节码文件时在程序的加载阶段,存在于内存的【代码区】
4. java 中万物皆对象
在java代码中,把内存代码区内保存的.class字节码内存空间,看做成一个对象,这个对象包含了java文件的所有内容。
反射是将数据类型占用的内存代码块空间看成一个Class对象,在这个对象中我们可以获得所有内容,包括私有的成员方法和私有的成员变量。
5. 反射必会方法【重点】
5.1 获取class 类对象的方法
Class Class.forName(String packageNameAndClassName);
Class类的静态成员方法,通过完整的包名.类名获取对应.class文件的Class对象
Class 类名.class;
通过类名.class方法,获取对应的Class类对象,通常用于方法的参数类型。
Class 类对象.getClass();
通过类对象获取对应.class的Class类对象,方法参数,或者说数据类型判断。
Class<?> forName = Class.forName("com.qfedu.a_reflect.Person");
Class<com.qfedu.a_reflect.Person> cls = Person.class;
Class<? extends Person> class1 = new Person().getClass();
这三个class 对象都是同一个Class对象
特点:
1. Class对象对应的是在内存代码区的.class文件占用的内存空间
2. Class引用数据类型变量保存的就是当前空间首地址
3. Java程序中,.class字节码文件有且之加载一次
4. .class文件占用的空间独一份,不管通过哪一种方式获取对应的Class类对象,都是同一个对象
5.2 Constructor 构造方法类涉及到的方法
public Constructor[] getConstructors();
获取当前Class类对象对应Java文件中,所有【public修饰构造方法的类对象数组】
public Constructor[] getDeclaredConstructors();
获取当前Class类对象对应Java文件中,所有【构造方法的类对象数组】,包括私有化构造方法。
public Constructor getConstructor(Class… initArgumentTypes);
根据指定的数据类型,来选择对应的构造方法,这里可能会抛出异常。只能获取public修饰的方法。
public Constructor getDeclaredConstructor(Class… initArgumentTypes);
根据指定的数据类型,来选择对应的构造方法,这里可能会抛出异常。这里可以获取指定参数类型私有化构造方法和非私有化构造方法
Object newInstance(Object… initArguments);
通过Constructor对象来调用,传入当前构造方法所需创建对象的初始化参数,创建对象。
[AppleScript] 纯文本查看 复制代码
Class<?> cls = Class.forName("com.qfedu.a_reflect.Person");//
//获取当前Person类内所有public构造方法
Constructor<?>[] constructors = cls.getConstructors();
for (Constructor<?> constructor : constructors) {
        System.out.println(constructor);
}
//暴力反射,获取Person类内所有的构造方法,包括私有化构造方法
Constructor<?>[] declaredConstructors = cls.getDeclaredConstructors();
or (Constructor<?> constructor : declaredConstructors) {
        System.out.println(constructor);
}

5.3 Method 成员方法
Method[] getDeclaredMethods();
获取类内所有public修饰的成员方法,包括从父类继承而来的public修饰方法。
Method[] getDeclaredMethods();
获取类内所有成员方法,但是不包括从父类继承而来的方法。
Method getMethod(String methodName, Class… parameterTypes);
根据指定的方法名和对应的参数类型,获取对应的public修饰的成员方法
Method getDeclaredMethod(String methodName, Class… parameterTypes);
根据指定的方法名和对应的参数类型,获取对应的成员方法,包括私有化成员方法,但是不
包括从父类继承而来的方法
Object invoke(Object obj, Object… arguments);
通过Method类对象调用,执行对应的方法,需要的参数
[AppleScript] 纯文本查看 复制代码
Class<?> cls = Class.forName("com.qfedu.a_reflect.Person");
//获取类内所有public修饰的成员方法,包括从父类继承而来的方法
Method[] methods = cls.getMethods();
for (Method method : methods) {
        System.out.println(method);
}
根//据指定的方法名和参数类型,获取类内public修饰的成员方法
Method game1 = cls.getMethod("game");
Method game2 = cls.getMethod("game", String.class);
Object obj = cls.getConstructor().newInstance();
//执行public修饰的成员方法
game2.invoke(obj, "WOT");

5.4 Field成员变量涉及到方法
Field[] getFields();
获取类内所有public修饰的成员变量
Field[] getDeclaredFields();
获取类内所有成员变量,包括私有化成员方法
Field getField(String fieldName);
获取指定变量名的成员变量对象,要求是public修饰的成员变量
Field getDeclaredField(String fieldName);
获取指定变量名的成员变量对象,包括private私有化修饰的成员变量
void set(Object obj, Object value);
设置指定调用者中对应成员变量的数据
Object get(Object obj);
获取指定调用者中指定成员变量的数据
[AppleScript] 纯文本查看 复制代码
Class<?> cls = Class.forName("com.qfedu.a_reflect.Person");
Object obj = cls.getConstructor().newInstance();
field.set(obj, 20);
//给予权限
id.setAccessible(true);
name.setAccessible(true);
id.set(obj, 1);
name.set(obj, "小米");

5.5 给予暴力反射私有化内容的权限操作
setAccessible(boolean flag);
给予Constructor,Method, Field对象,私有化内容,操作权限设置
true表示可以操作







欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2