您的位置:首页 > 编程语言 > Java开发

JavaSE第六十四讲:使用反射机制调用对象的私有方法、访问对象的私有成员变量

2013-01-05 11:09 1041 查看
1. 反射打破面向对象的封装性,以下例子实现外部类通过反射机制访问类的私有方法:

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐