关于setAccessible方法的使用
- Method和Field、Constructor对象都有setAccessible()方法。
- setAccessible是启动和禁用访问安全检查的开关。
- 参数值为true则指示反射的对象在使用时应该取消Java语言访问检查。
提高反射的效率。如果代码中必须用反射,而该句代码需要频繁的被调用,那么请设置为true。
使得原本无法访问的私有成员也可以访问
- 参数值为false则指示反射的对象应该实施Java语言访问检查。
调用指定属性
方式一
在反射机制中,可以直接通过Field类操作类中的属性,通过Field类提供的set()和 get()方法就可以完成设置和取得属性内容的操作。
public void testField() throws Exception {Class clazz = Person.class;//创建运行时类的对象Person p = (Person) clazz.newInstance();//获取指定的属性:要求运行时类中属性声明为public//通常不采用此方法Field id = clazz.getField("id");/*设置当前属性的值set():参数1:指明设置哪个对象的属性 参数2:将此属性值设置为多少*/id.set(p,1001);/*获取当前属性的值get():参数1:获取哪个对象的当前属性值*/int pId = (int) id.get(p);System.out.println(pId);}
方式二
public Field getField(String name)返回此Class对象表示的类或接口的指定的 public的Field。 public Field getDeclaredField(String name)返回此Class对象表示的类或接口的指定的Field。
在Field中:public Object get(Object obj) 取得指定对象obj上此Field的属性内容 public void set(Object obj,Object value)设置指定对象obj上此Field的属性内容
/*如何操作运行时类中的指定的属性 -- 需要掌握*/@Testpublic void testField1() throws Exception {Class clazz = Person.class;//创建运行时类的对象Person p = (Person) clazz.newInstance();//1. getDeclaredField(String fieldName):获取运行时类中指定变量名的属性Field name = clazz.getDeclaredField("name");//2.保证当前属性是可访问的name.setAccessible(true);//3.获取、设置指定对象的此属性值name.set(p,"Tom");System.out.println(name.get(p));//3.获取、设置指定对象的静态属性值// name.set(Person.class,"男");//// System.out.println(name.get(p));}
调用指定方法
通过反射可以调用类中的方法,通过Method类完成。
步骤:
- 通过Class类的
getMethod(String name,Class…parameterTypes)方法取得一个Method对象,并设置此方法操作时所需要的参数类型。 - 之后使用
Object invoke(Object obj, Object[] args)进行调用,并向方法中传递要设置的obj对象的参数信息。
invoke(Object obj, Object[] args)的说明:
- Object 对应原方法的返回值,若原方法无返回值,此时返回null
- 若原方法若为静态方法,此时形参Object obj可为null
- 若原方法形参列表为空,则Object[] args为null
若原方法声明为private,则需要在调用此invoke()方法前,显式调用方法对象的setAccessible(true)方法,将可访问private的方法。
/*如何操作运行时类中的指定的方法 -- 需要掌握*/@Testpublic void testMethod() throws Exception {Class clazz = Person.class;//创建运行时类的对象Person p = (Person) clazz.newInstance();/*1.获取指定的某个方法getDeclaredMethod():参数1 :指明获取的方法的名称 参数2:指明获取的方法的形参列表*/Method show = clazz.getDeclaredMethod("show", String.class);//2.保证当前方法是可访问的show.setAccessible(true);/*3. 调用方法的invoke():参数1:方法的调用者(那个对象调用的) 参数2:给方法形参赋值的实参invoke()的返回值即为对应类中调用的方法的返回值。*/Object returnValue = show.invoke(p,"CHN"); //String nation = p.show("CHN");System.out.println(returnValue);System.out.println("*************如何调用静态方法*****************");// private static void showDesc()Method showDesc = clazz.getDeclaredMethod("showDesc");showDesc.setAccessible(true);//如果调用的运行时类中的方法没有返回值,则此invoke()返回null// Object returnVal = showDesc.invoke(null);Object returnVal = showDesc.invoke(Person.class);System.out.println(returnVal);//null}
调用指定构造器
步骤如下:
- 通过Class类的
getDeclaredConstructor(Class … parameterTypes)取得本类的指定形参类型的构造器 - 向构造器的形参中传递一个对象数组进去,里面包含了构造器中所需的各个参数。
通过Constructor实例化对象。
```java / 如何调用运行时类中的指定的构造器 / @Test public void testConstructor() throws Exception {Class clazz = Person.class;//private Person(String name)/*1.获取指定的构造器getDeclaredConstructor():参数:指明构造器的参数列表*/Constructor constructor = clazz.getDeclaredConstructor(String.class);//2.保证此构造器是可访问的constructor.setAccessible(true);//3.调用此构造器创建运行时类的对象Person per = (Person) constructor.newInstance("Tom");System.out.println(per);
}
}
```
