JavaSE第六十四讲:使用反射机制调用对象的私有方法、访问对象的私有成员变量
2013-01-05 11:09
1041 查看
1. 反射打破面向对象的封装性,以下例子实现外部类通过反射机制访问类的私有方法:
Exception in thread "main" java.lang.IllegalAccessException: Class com.ahuier.reflect.PrivateTest can not access a member of class com.ahuier.reflect.Private with modifiers "private"
at sun.reflect.Reflection.ensureMemberAccess(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at com.ahuier.reflect.PrivateTest.main(PrivateTest.java:12)
[原因不能访问私有方法的错误,查看JDK Doc文档中的Method的父类AccessibleObject]
public class AccessibleObject extends Object implements AnnotatedElement
The AccessibleObject class is the base class for Field, Method and Constructor objects. It provides the ability to flag a reflected object as suppressing default Java language access control checks when it is used.
[它提供了一种标志方法对象可以作为压制Java语言检查访问控制的权利]
查看这个类的setAccessible()方法
public void setAccessible(boolean flag) throws SecurityException
Set the accessible flag for this object to the indicated boolean value. A value of true indicates that the reflected object should suppress Java language access checking when it is used.
[将其boolean值设置为真,则可以压制Java语言检查访问控制的权利]
所以以上的第二个程序修改后,整个程序如下所示
hello: Hello
【说明】:通过反射实现私有方法的调用,注意这种方式再以后学习框架的时候是很经常用到的。很用联系的
再获得class对象之后,需要调用他们的Method方法,获得Method对象,通过Method对象调用invoke方法实现调用,查看JDK Doc中的Class类获得Method对象有以下两种方法,比较他们的区别
getMethod
public Method getMethod(String name, Class<?>... parameterTypes) throws NoSuchMethodException,SecurityException
Returns a Method object that reflects the specified public member method of the class or interface represented by this Class object.
[返回一个Method对象,它通过这个类的class对象所代表的类和或者接口反射指定的公有成员变量],所以这边只能返回public方法。
getDeclaredMethod
public Method getDeclaredMethod(String name, Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException
Returns a Method object that reflects the specified declared method of the class or interface represented by this Class object.
[返回一个Method对象,它通过这个类的class对象所代表的类和或者接口反射指定的声明成员变量],这边可以返回非public的,只要有声明即可。
2. 现在再举一个例子,掌握它。
将如下程序的私有属性name通过反射的方式将其改为“lisi”,将其打印。具体步骤可以根据上面方式,同时查看JDK Doc文档相关方法。
法一:AHuier写的程序
编译执行结果:
lisi
法二:张龙老师写的程序
package com.ahuier.reflect;
import java.lang.reflect.Field;
public class PrivateTest2 {
public static void main(String[] args) throws Exception{
Private2 p = new Private2();
Class<?> classType = p.getClass();
Field field = classType.getDeclaredField("name");
field.setAccessible(true);
//查看JDK Doc文档Field里面的set()方法,用来重设值。
field.set(p, "lisi"); //set()方法第一个参数表示调用set的对象,第二个参数填充进去的值
System.out.println(p.getName());
}
}
编译执行结果:
lisi
package com.ahuier.reflect; public class Private { /* * 通过反射机制调用对象的私有方法 */ private String sayHello(String name){ return "hello: " + name; } }
package com.ahuier.reflect; import java.lang.reflect.Method; public class PrivateTest { public static void main(String[] args) throws Exception{ Private p = new Private(); Class<?> classType = p.getClass(); //获得class对象 Method method = classType.getDeclaredMethod("sayHello", new Class[]{String.class}); String str = (String)method.invoke(p, new Object[]{"Hello"}); System.out.println(str); } }编译执行结果:
Exception in thread "main" java.lang.IllegalAccessException: Class com.ahuier.reflect.PrivateTest can not access a member of class com.ahuier.reflect.Private with modifiers "private"
at sun.reflect.Reflection.ensureMemberAccess(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at com.ahuier.reflect.PrivateTest.main(PrivateTest.java:12)
[原因不能访问私有方法的错误,查看JDK Doc文档中的Method的父类AccessibleObject]
public class AccessibleObject extends Object implements AnnotatedElement
The AccessibleObject class is the base class for Field, Method and Constructor objects. It provides the ability to flag a reflected object as suppressing default Java language access control checks when it is used.
[它提供了一种标志方法对象可以作为压制Java语言检查访问控制的权利]
查看这个类的setAccessible()方法
public void setAccessible(boolean flag) throws SecurityException
Set the accessible flag for this object to the indicated boolean value. A value of true indicates that the reflected object should suppress Java language access checking when it is used.
[将其boolean值设置为真,则可以压制Java语言检查访问控制的权利]
所以以上的第二个程序修改后,整个程序如下所示
package com.ahuier.reflect; import java.lang.reflect.Method; public class PrivateTest { public static void main(String[] args) throws Exception{ Private p = new Private(); Class<?> classType = p.getClass(); //获得class对象 Method method = classType.getDeclaredMethod("sayHello", new Class[]{String.class}); method.setAccessible(true);//压制Java语言的访问控制检查 String str = (String)method.invoke(p, new Object[]{"Hello"}); System.out.println(str); } }编译执行结果:
hello: Hello
【说明】:通过反射实现私有方法的调用,注意这种方式再以后学习框架的时候是很经常用到的。很用联系的
再获得class对象之后,需要调用他们的Method方法,获得Method对象,通过Method对象调用invoke方法实现调用,查看JDK Doc中的Class类获得Method对象有以下两种方法,比较他们的区别
getMethod
public Method getMethod(String name, Class<?>... parameterTypes) throws NoSuchMethodException,SecurityException
Returns a Method object that reflects the specified public member method of the class or interface represented by this Class object.
[返回一个Method对象,它通过这个类的class对象所代表的类和或者接口反射指定的公有成员变量],所以这边只能返回public方法。
getDeclaredMethod
public Method getDeclaredMethod(String name, Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException
Returns a Method object that reflects the specified declared method of the class or interface represented by this Class object.
[返回一个Method对象,它通过这个类的class对象所代表的类和或者接口反射指定的声明成员变量],这边可以返回非public的,只要有声明即可。
2. 现在再举一个例子,掌握它。
将如下程序的私有属性name通过反射的方式将其改为“lisi”,将其打印。具体步骤可以根据上面方式,同时查看JDK Doc文档相关方法。
package com.ahuier.reflect; public class Private2 { private String name = "zhangsan"; public String getName(){ return name; } }
法一:AHuier写的程序
package com.ahuier.reflect; import java.lang.reflect.Field; public class PrivateTest2 { public static void main(String[] args) throws Exception{ Private2 p = new Private2(); Class<?> classType = p.getClass(); Field field = classType.getDeclaredField("name"); field.setAccessible(true); String str = classType.getName(); str = "lisi"; System.out.println(str); } }
编译执行结果:
lisi
法二:张龙老师写的程序
package com.ahuier.reflect;
import java.lang.reflect.Field;
public class PrivateTest2 {
public static void main(String[] args) throws Exception{
Private2 p = new Private2();
Class<?> classType = p.getClass();
Field field = classType.getDeclaredField("name");
field.setAccessible(true);
//查看JDK Doc文档Field里面的set()方法,用来重设值。
field.set(p, "lisi"); //set()方法第一个参数表示调用set的对象,第二个参数填充进去的值
System.out.println(p.getName());
}
}
编译执行结果:
lisi
相关文章推荐
- 反射(四)使用反射机制调用对象的私有方法及成员变量
- 反射机制的概述和字节码对象的获取,通过反射获取构造方法并使用;通过反射获取成员变量并使用;通过反射获取私有成员变量并使用;通过反射获取成员方法并使用
- 使用类的反射机制来访问类的私有成员变量
- 论java之反射机制,访问类中私有变量,调用私有方法
- java 使用反射机制来获取私有方法和成员变量
- 使用反射机制实现对类中私有方法的调用
- 为什么一个对象调用的类方法可以访问该类其他对象的私有成员
- 通过反射访问对象的私有变量和执行私有方法
- java 程序加载过程---3--类中申明同时申明类的静态对象 创建类的实例 访问类的静态变量 调用类的静态方法 使用反射方法 初始化类的子类对象 直接使用java.exe 调用某个类
- 私有方法是封闭的?使用反射来调用一个对象的私有方法。
- 使用反射依导航路径调用对象成员方法,或返回对象子、孙属性或字段成员[转]
- 通过反射,如何操作私有成员变量(取/赋值),如何调用私有方法?
- 通过操作地址的方法来访问C++类对象中私有成员变量
- Java记录 -88- 利用反射机制调用对象的私有方法和属性
- 访问C++类对象中私有成员变量的方法
- 访问C++类对象中私有成员变量的方法
- 定义一个包含私有成员变量和函数的类,再定义一个内部类,在内部类函数中访问外部成员变量,并调用外部函数。在外部类函数中创建内部类对象,调用内部类函数
- OC 继承子类对象调用方法机制 子类对象访问父类中的实例变量
- java中的反射机制——如何访问私有成员的私有方法
- OC中继承子类对象调用方法机制 子类对象访问父类中的实例变量