good good study, day day up!

Java 如何突破访问权限限制

2011-11-08

学过Java的都知道,Java类中所有的属性与方法都有访问修饰符(private,public,protected以及默认访问权限).

在编写一个程序的时候,我们通常会把一些不希望让别人直接获取属性或方法隐藏起来,这时候对该属性或方法加private修饰符就能防止被别人直接使用.

但是有时候我们希望获取一个类的私有成员变量或者是调用类的私有方法,私有的属性或方法用一般的点操作符是无法直接调用的.这个时候我们就需要用到Java的反射机制了.
代码示例:

//PrivateDemo.java
public class PrivateDemo {
	private String hello = "hello";
	private String sayHello(String s) {
		return hello + s;
	}
	//say()方法打出private String hello
	public void say() {
		System.out.println("String hello = "+hello);
	}
}
//BreakPrivate.java
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class BreakPrivate {
	public static void main(String[] args) throws Exception {
		// 首先要创建PrivateDemo的实例,之后才可能访问改类的成员变量与成员方法
		PrivateDemo p = new PrivateDemo();
		// 打印出p的私有成员变量hello的值
		p.say();
		// 获取PrivateDemo类的类型信息
		Class<?> classType = PrivateDemo.class;
		// 通过类型信息获得名为hello的成员变量对象
		Field f = classType.getDeclaredField("hello");
		/*
		 * f.setAccessible(bool b)方法:如果参数为false则Java会对f的访问权限作检查,
		 * 如果设置为true则Java不会对f的访问权限作检查
		 */
		f.setAccessible(true);

		// 将f的值设置为"change",set方法的第一个变量为需要修改的成员变量所属的实例,第二
		// 个参数为需要修改成的值
		// 调用set方法之后p.hello的值就变成了"change"
		f.set(p, "change");

		// 通过类型信息获得名为sayHello且有一个String类型的参数的方法对象
		Method method = classType.getDeclaredMethod("sayHello", String.class);

		// 抑制Java的访问权限检查
		method.setAccessible(true);
		// 执行method对应的方法,p表示方法所属的类的实例,"world"为方法参数
		String s = (String) method.invoke(p, "world");
		System.out.println(s);
		// 再次将p的私有成员hello的值输出
		p.say();
	}
}

 


知识共享许可协议本作品采用知识共享署名 2.5 中国大陆许可协议进行许可,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名(chen)并包含原文链接

作者:chending | Categories:Java | Tags:

一条评论

  1. Carla说道:

    博主很强大,我支持

发表评论

电子邮件地址不会被公开。 必填项已用*标注