通过反射操作字节码class文件。
反射相关类在 java.lang.reflect.* 包下,
- java.lang.Class:字节码,一个类型 java.lang.reflect.Methond:代表字节码中的方法字节码,
- java.lang.reflect.Constructor:代表字节码中的构造方法字节码,
- java.lang.reflect.Field:代表字节码中的属性字节码
获取字节码三种方式
- Clasd.forName(“”) 参数必须是完整类名,是一个静态方法
- 对象.getClass()方法
- 类型.class属性
获取到class,能干什么?
- 通过Class的newInstance()方法来实例化对象。
- 注意:newInstance()方法内部实际上调用了无参数构造方法,必须保证无参数构造方法存在,否则实例化异常
- 只希望类的静态代码块执行,其他代码不执行,就用 Class.forName()
- 资源绑定器uril包下 ResourceBundle.getBundle(“文件名”) 获取类路径下文件,文件必须是properties
反射获取属性field
Class myClass = Class.forName(“类的包路径 com.xxxx.java.bean.My”);
myClass.getFields(); 这个方法只能获取pubic修饰的field对象
myClass.getDeclaredFields(); 可获取全部field对象,返回值是field数组
Fields[] fs=myClass.getDeclaredFields();
for (Field field:fs){
Class fieldType =field.getType(); 获取类型
String fName=fieldType.getSimpleName(); 获取类名
fName=fieldType.getName();获取完整类名
int i =field.getModifiers()获取属性的修饰符列表,返回的是int值,要转换为字符串
String modifierString=Modifier.toString(i);
}
通过反射机制反编译一个类的属性field
反射机制给对象赋值
Class myClass=Class.forName(“com.xxxxx.java.bean.My”);
Object obj = myClass.newInstance();
Field ageField=myClass.getDeclaredField(name:“age”);
ageField.set(obj,30);
ageField.get(obj);
打破封装访问私有属性
- name属性是prviate修饰
nameField.setAccessible(true);
nameField.set(obj,“Trump”);
nameField.get(obj);
- 缺点:打破封装可能会给黑客留下机会
可变长度参数 … 修饰
- 1.参数要求0-n个
- 2.可变长度参数必须在方法定义中只能定义在最后一个,不能定义多个或其他位置
- 3.可以当做数组
反射Methond
Method [] methods=myClass.getDeclaredMethods();
for(Method method:methods)
{
method.getName(); 方法名
method.getReturnType().getSimpleName();获取方法返回值类型
Modifier.toString(method.getModifiers);获取修饰符列表
Class[] paraterTypes=method.getParameterTypes();
获取方法修饰符列表,一个方法参数可能有多个
}
反编译method
- 无法反编译方法体
反射机制调用一个对象的方法
Class myClass=Class.forName(“com.xxxxx.java.bean.My”);
Object obj = myClass.newInstance();
Method myMrthod=myClass.getDeclaredMethod(“myMethod”,String.class,String.class);
Object retValue=myMethod.invoke(obj,“admin”,“123456”);
- 反射机制让代码具有通用性,可变化内容可以写到配置文件
反射constructor构造方法
Constructor[] contructors =myClass.getDeclaredConstructor();
用反射new对象
1,无参构造new对象 getInstance
2. 有参数构造方法new对象
Constructor con=c.getDeclaredConstructor(int.class,String.class);
con.newInstance(110,“myname”);
反射获取父类和其实现接口
Class superClass=myClass.getSuperclass();
Class[] interfaces=myClass.getInterfaces();