反射能做什么?
反射可以根据Class对象获取和设置它的所有,字段、方法、构造方法、类的注解,可以操作任何修饰字段、方法的能力当然包括私有修饰符
反射的边界是什么?
反射只能获取方法的返回类型、返回值、参数、并不能获得方法中的执行代码,当然我们可以通过代理动态注入新的执行代码但原代码永远存在且不变。
运用反射注意什么?
1、反射本质是获得Class对象的属性、方法,而我们所有对象都公用一个Class类型,所以用反射调用方法时需要给它一个具体的对象,这个对象就是Class对象转换后的对象(往往我们是用newInstance()方法把Class对象转换为具体的某个对象)
2、反射中类型是用的整数常量如下:
public static final int ABSTRACT 1024
public static final int FINAL 16
public static final int INTERFACE 512
public static final int NATIVE 256
public static final int PRIVATE 2
public static final int PROTECTED 4
public static final int PUBLIC 1
public static final int STATIC 8
public static final int STRICT 2048
public static final int SYNCHRONIZED 32
public static final int TRANSIENT 128
public static final int VOLATILE 64
3、方法、字段、构造方法都继承与AccessibleObject对象
这个对象可以操作访问权限和字段方法注解,最常用的setAccessible(boolean flag),设置为true就可以访问私有变量
4、Class 对象的以下方法需要注意:
getFields()
返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段。
getDeclaredFields()
返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段。
getMethods()
返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法。
getDeclaredFields()
返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段。
反射代码实例:
public class Cat {
// 静态模块
static {
System.out.println("我是静态内容");
}
// 无参构造方法
public Cat() {
System.out.println("我是构造方法");
}
// 有参构造方法
public Cat(String str,int num) {
System.out.println("有参构造方法"+str+num);
}
List<Cat> catList=new ArrayList<Cat>();
//静态变量
public static int AGE=10;
private String catName;
public String catPlay="玩溜溜球";
public void setCatName(String catName) {
this.catName = catName;
}
/**
*
* @return 获取猫的名字
*/
public String getCatName() {
return catName;
}
}
具体反射代码:
//构造方法
@Test
public void testReflectConstuctor() throws Exception{
//1、获得Class对象
Class<?> cl=Class.forName("com.lovo.Cat");
//2、获取所有构造方法
Constructor cs[]=cl.getConstructors();
//3、获取构造方法名字、参数,构造方法并无返回值
for(Constructor c:cs){
int i=c.getModifiers();
/**
* public static final int ABSTRACT 1024
public static final int FINAL 16
public static final int INTERFACE 512
public static final int NATIVE 256
public static final int PRIVATE 2
public static final int PROTECTED 4
public static final int PUBLIC 1
public static final int STATIC 8
public static final int STRICT 2048
public static final int SYNCHRONIZED 32
public static final int TRANSIENT 128
public static final int VOLATILE 64
*/
//获得修饰符
System.out.println("修饰符常量="+i);
//获取方法名
String methodeName=c.getName();
System.out.println(methodeName);
//获取参数类型素组
Class[] typeClasss=c.getParameterTypes();
for(Class tcl:typeClasss){
System.out.println("构造方法参数类型按照顺序"+tcl.getName());
}
// 使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。
if(typeClasss.length>0){
//有参构造方法
c.newInstance("小花猫",5);
}else{
//无参构造方法
c.newInstance();
}
}
}
@Test
public void testReflectFiled() throws Exception{
//1、获得Class对象
Class<?> cl=Class.forName("com.lovo.Cat");
//获取非私有字段数组
//Field fs[]= cl.getFields();
//获取所有字段数组
Field fs[]= cl.getDeclaredFields();
//循环获取所有字段
for(Field f:fs){
//AccessibleObject类是 Field、Method 和 Constructor 对象的基类。
//此方法为AccessibleObject类的方法,让反射是无忌惮的访问所有修饰类型
f.setAccessible(true);
System.out.println("字段修饰="+f.getModifiers());
System.out.println("字段类型="+f.toGenericString());
System.out.println("字段名称="+f.getName());
System.out.println("获得值="+f.get(cl.newInstance()));
//给catName字段设置新的值
if(f.getName().equals("catName")){
Object obj= cl.newInstance();
f.set(obj,"小白猫");
//获取新值
Cat c=(Cat)obj;
System.out.println("新值="+c.getCatName());
}
}
}
@Test
public void testRefletMethod() throws Exception{
//1、获得Class对象
Class<?> cl=Class.forName("com.lovo.Cat");
//获取所有非私有方法
//Method []ms=cl.getMethods();
//获取所有方法
Method []ms=cl.getDeclaredMethods();
//转换为具体的对象
Object obj=cl.newInstance();
for(Method m:ms){
System.out.println("返回方法修饰="+m.getModifiers());
System.out.println("返回方法返回类型="+m.getGenericReturnType().toString());
System.out.println("返回方法名="+m.getName());
System.out.println("获取方法参数类型"+m.getGenericParameterTypes());
if(m.getName().equals("setCatName")){
//设置
m.invoke(obj, "新猫咪");
}
}
for(Method m:ms){
if(m.getName().equals("getCatName")){
System.out.println("返回值="+m.invoke(obj));
}
}
}