Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/394.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java阻止在类外调用私有或受保护的方法_Java_Reflection_Private - Fatal编程技术网

Java阻止在类外调用私有或受保护的方法

Java阻止在类外调用私有或受保护的方法,java,reflection,private,Java,Reflection,Private,让我们假设我已经创建了一个名为Foo的Java库,并且在该库中有一个名为Bar的类。让我们进一步假设在Bar类中,我有一个私有方法,名为fooBar public class Bar { //... private Object fooBar() { //Do something } //... } 使用类中编写的代码可以毫无困难地运行此方法,如下所示: public static Object runMethod(Object object,

让我们假设我已经创建了一个名为
Foo
的Java库,并且在该库中有一个名为
Bar
的类。让我们进一步假设在
Bar
类中,我有一个私有方法,名为
fooBar

public class Bar {
    //...
    private Object fooBar() {
        //Do something
    }
    //...
}
使用类中编写的代码可以毫无困难地运行此方法,如下所示:

public static Object runMethod(Object object, String methodName) {
    Method method = object.getClass().getDeclaredMethod(methodName);
    method.setAccessible(true);
    return method.invoke(object);
}
public class Bar {
    //...
    private Object fooBar() {
        try {
            throw new CheckIfCalledFromMethodException(); 
        } catch(CheckIfCalledFromMethodException e) {
            //here you have access to stack trace in your exception
        }

        //Do something
    }
    //...
}

然而,让我们假设我们打算为
fooBar
阻止这种习惯。我们怎么能做那样的事?我们是否应该从某个地方获取堆栈跟踪并检查调用它的位置?还是我们应该做点别的?

你需要一个安全经理

安全管理器是定义安全策略的对象 应用此策略指定不安全或不安全的操作 敏感的安全策略不允许的任何操作都会导致 要抛出的SecurityException。应用程序还可以查询其 security manager以发现允许哪些操作


它支持禁止
setAccessible()
通过反射调用私有和受保护的方法。

我认为如果你想达到极限,可以得到如下堆栈跟踪:

public static Object runMethod(Object object, String methodName) {
    Method method = object.getClass().getDeclaredMethod(methodName);
    method.setAccessible(true);
    return method.invoke(object);
}
public class Bar {
    //...
    private Object fooBar() {
        try {
            throw new CheckIfCalledFromMethodException(); 
        } catch(CheckIfCalledFromMethodException e) {
            //here you have access to stack trace in your exception
        }

        //Do something
    }
    //...
}
我创建了一个简单的场景,其中它检查调用该类的第二个实例是同一个对象还是其他对象

public class StackTraceTest {
    private void execute() {
        try {
            throw new Exception();
        } catch (Exception e) {
            /*for(int i = 0; i < e.getStackTrace().length; i++) {
                StackTraceElement stackTraceElement = e.getStackTrace()[i];
                System.out.println(stackTraceElement.getFileName());
            }
            System.out.println("");
            e.printStackTrace();*/
            if(!e.getStackTrace()[1].getFileName().equals(StackTraceTest.class.getSimpleName() + ".java")) {
                throw new IllegalAccessError("Illegal Access.");
            }
        }
    }

    public void executeExternal() {
        this.execute();
    }
}

因此,我想可以使用stack trace element magic进行检查,但您应该检查这是否真的有效,这是非常粗糙的,我刚刚在一秒钟前将其整理好。

您已经不鼓励人们将您的方法称为私有。我已经对您的答案进行了投票,因为它应该有效。然而,这显然也是我正在考虑的解决方案。我问我的问题是希望有更好的办法。然而,菲尔·安德森的回答显然优于这个想法。我也投了更高的票,我接受了。的确,但我很好奇,如果一个人没有权限设置SecurityManager等,我会看到它在起作用。没问题,我相信你的答案是好的,我在我的问题中也提出了同样的建议,写一个说明想法的答案很好。当然值得投票表决,但是,我们必须承认,另一个答案是优越的,当另一个解决方案因某种原因不可用时,这一个是一个解决办法。