反射是一项底层技术,相当牛逼!
课程前半段没感觉到它有多牛逼,
只是认为它只是用来描述类的对象。
在后半段的课程中,通过反射的方法居然可以操作修改私有属性,就觉得有点强大的不要不要的了。
白板笔记本:
类是用来描述一组对象的,反射机制是用来描述一组类的,
每一个类都有属性、方法、构造方法,
每一个类都有权限修饰符、特征修饰符,
所有的类也具有相同的特征。
【类型】 | 【作用】 |
---|---|
Class | 用来描述类本身 |
Package | 用来描述类所属的包 |
Field | 用来描述类中的属性 |
Method | 用来描述类中的方法 |
Constructor | 用来描述类中的构造方法 |
Annotation | 用来描述类中的注解,例如:@Override |
关于注解,拓哥提了一嘴:
—-注解可以放在类、属性、方法、构造方法上面 —-注解可以放在参数前面 |
---|
———思考的问题———如何获取Class?———
1、通过这三个方法来获取:
① Class clazz = Class.forName(“包名.类名”); (String类型的参数)
通过类的全名**字来获取当前的类
② Class clazz = 类名.class;
它是属性,调取的是关键字例如:person.class;
类名必须存在**
③ Class clazz = 对象.getClass();
通过对象.getClass,它是Object类中的方法,
每个引用类型都有这个方法。
2.Class中的常用方法
① int result = getModifiers();
用来获取类的修饰符(权限 特征),返回值是int类型
每一个修饰符用一个整数来进行表示
从0开始—>1、2、4、8、16、32、64、128、256、512、1024、2048 |
---|
0—>表示默认不写 | 1—>表示public | 2—>表示private |
---|---|---|
4—>表示protected | 8—>表示static | 16—>表示final |
32—>表示synchronized | 64—>表示volatile | 128—>表示transient |
256—>表示native | 512—>表示interface | 1024—>表示abstract |
② String name = getName(); --->获取类全名(包含包名)<br /> ③ String simpleName = getSimpleName(); --->获取类名<br /> ④ Package p = getPackage(); --->获取包名<br />p.getName(); <br /> ⑤ Class sclazz = getSuperClass(); --->获取超类(父类)<br /> ⑥ Class[] classes = getInterface(); --->用来获取当前clazz的所有父接口<br /> ⑦ Object obj = newInstance(); --->默认调用无参数构造方法来创建对象<br /> ⑧ Field f = getField("属性名"); --->只能获取的名字是已知的<br /> Field[] fs = getFields(); --->可以获取包括继承关系的全部属性的名字<br /> 这两个方法只能获取公有的属性,但可以获取继承过来的父类属性<br /> ⑨ getDeclaredField("属性");<br /> Field[] fs = getDeclaredFields();<br /> 这两个方法能获取公有的和私有的属性,但只能获取本类中的属性
3.Field类中的常用方法
【返回值】 | 【赋值】 | 【方法名】 |
---|---|---|
int | = | getModifers() |
Class | = | getType() |
String | = | getName() |
操作属性,向里面存值:set(对象,值) —>存的是对象和值
操作属性,从里面取值:值 = get(对象) —>参数是个对象,返回的是值
setAccessable(true); 可以修改属性被操作
对象 = new();//创建对象空间,当前对象空间里有自己的一套元素(属性、方法)
对象.属性 = 值;
属性 = 类.getField();
属性.赋值(哪个对象,值);
值 = 对象.属性 值 = 属性.取值(哪个对象)
4.通过一个小应用演示反射reflect可以操作并且修改String类的值value
package testreflect;
import java.lang.reflect.Field;
public class ChangeStringValue {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
String str = new String("abc");
System.out.println(str);
//反射的技术,可以获取私有属性,且可以操作它
//1.想要操作属性,必须先获取String类对应的Class
Class clazz = str.getClass();
//2.通过clazz获取类中的Value属性
Field field = clazz.getDeclaredField("value"); //field表示String类下的属性
//3.不能直接操作属性的值,必须先将私有属性设置为可被操作
field.setAccessible(true);
//属性原本是 final修饰的 char[]数组 的value --> private final char[] value = {'a','b','c'};
//4.获取value属性里面的值,它是数组,所以里面存的是一个内存地址@AOI783之类的东西.
//我们不修改地址,但要修改地址对应的字符,所以要获取内存地址
char[] temp = (char[])field.get(str);
//5.通过temp的地址引用,找到真实String对象中的数组,去修改数组内的每一个元素
temp[0] = '张'; temp[1] = '三'; temp[2] = '哥';
//6.最终输出一个str的值
System.out.println(str);
}
}
——————输出结果——————
思考:反射机制这么强大,它甚至可以修改String类型的值,
那么是不是可以修改支付系统的签名串?把未支付变成已支付?