反思:为什么有类似setAccessible()的方法?

时间:2012-09-02 16:13:20

标签: java reflection language-design access-modifiers

只是想知道,为什么发明Java的人会编写类似setAccessible(boolean flag)的方法,这会使访问修饰符(特别是私有的)无用,无法保护字段,方法和构造函数不被覆盖?请看以下简单示例:

public class BankAccount
{
    private double balance = 100.0;

    public boolean withdrawCash(double cash)
    {
        if(cash <= balance)
        {
            balance -= cash;
            System.out.println("You have withdrawn " + cash + " dollars! The new balance is: " + balance);
            return true;
        }
        else System.out.println("Sorry, your balance (" + balance + ") is less than what you have requested (" + cash + ")!");
        return false;
    }
}

import java.lang.reflect.Field;

public class Test
{
    public static void main(String[] args) throws Exception
    {
        BankAccount myAccount = new BankAccount();
        myAccount.withdrawCash(150);

        Field f = BankAccount.class.getDeclaredFields()[0];
        f.setAccessible(true);
        f.set(myAccount, 1000000); // I am a millionaire now ;)

        myAccount.withdrawCash(500000);
    }
}

输出:

Sorry, your balance (100.0) is less than what you have requested
(150.0)! You have withdrawn 500000.0 dollars! The new balance is: 500000.0

2 个答案:

答案 0 :(得分:6)

因为某些代码是可信代码 - 即,如果本地应用程序想要这样做,也许这不是什么大问题。对于不受信任的代码,但是 - 即applet,或者Web启动应用程序,或RMI存根或任何其他下载的代码 - 都有一个SecurityManager(通常基于在政策文件上)有机会说“抱歉,查理”并拒绝setAccessible()请求。

答案 1 :(得分:2)

好吧,一旦你发布了一个Java程序,任何人都可以自由地进行反向工程或反编译,所以如果有人想要它,那么他们可能无论如何都可以访问你的“私有”。

可以做的是禁止任何外国代码访问运行时中的内容。也就是说,如果您使用其他人的代码,则可以在使用这些库之前禁用反射,访问文件等。

搜索ClassLoader和Security Manager以了解更多信息。 Here看起来很相似。