[英]Why does accessing a private member of an outer class using reflection throw IllegalAccessException?
Given the code example below, why does accessUsingReflection
-> theAnswer.get( outer )
throw an IllegalAccessException
whereas accessDirectly
prints 42 just fine? 鉴于下面的代码示例,为什么
accessUsingReflection
- > theAnswer.get( outer )
抛出IllegalAccessException
而accessDirectly
打印42就好了?
Exception in thread "main" java.lang.IllegalAccessException: Class Outer$Inner can not access a member of class Outer with modifiers "private"
According to this SO answer , I'd expect it to work as the access does happen "(...) from a class that is allowed to access it". 根据这个SO答案 ,我希望它能够正常工作,因为访问确实发生了“(......)来自允许访问它的类”。
import java.lang.reflect.Field;
public class Outer
{
private int theAnswer = 42;
public static class Inner
{
public void accessDirectly( Outer outer )
{
System.out.println( outer.theAnswer );
}
public void accessUsingReflection( Outer outer ) throws NoSuchFieldException,
SecurityException,
IllegalArgumentException,
IllegalAccessException
{
Field theAnswer = Outer.class.getDeclaredField( "theAnswer" );
// Of course, uncommenting the next line will make the access using reflection work.
// field.setAccessible( true );
System.out.println( theAnswer.get( outer ) );
}
}
public static void main( String[] args ) throws NoSuchFieldException,
SecurityException,
IllegalArgumentException,
IllegalAccessException
{
Outer outer = new Outer();
Inner inner = new Inner();
inner.accessDirectly( outer );
inner.accessUsingReflection( outer );
}
}
"Why" questions like these can tricky to answer - there are many layers of "why", including why did the designers choose to do this? “为什么”这样的问题可能很难回答 - 有很多层面的“为什么”,包括为什么设计师选择这样做? what part of the specification allows this?
规范的哪一部分允许这个? what are the underlying technical details?
什么是底层技术细节?
I'll answer the last of those, but I'm not sure if that's what you're after. 我会回答最后一个,但我不确定这是不是你要追求的。
The Java runtime (JVM, security model, etc) is largely ignorant about inner classes. Java运行时(JVM,安全模型等)在很大程度上不了解内部类。 They are, for the most part, a language issue.
在大多数情况下,它们是语言问题。
One of the consequences of that is that compiler uses some hidden tricks to allow inner/outer classes to access each other's private members, even though the runtime would not ordinarily allow it. 其中一个后果是编译器使用一些隐藏的技巧来允许内部/外部类访问彼此的私有成员,即使运行时通常不允许它。
One of those tricks is that your accessDirectly
method is not actually accessing the field directly. 其中一个技巧是你的
accessDirectly
方法实际上并没有直接访问该字段。 The compiler adds a hidden method onto the outer classes that returns the value of theAnswer
. 编译器将一个隐藏方法添加到返回
theAnswer
值的外部类。
The field ( theAnswer
) is still private, and as far as the runtime security model is concerned, cannot be accessed outside of the owning (outer) class. 字段(
theAnswer
)仍然是私有的,就运行时安全模型而言,不能在拥有(外部)类之外访问。
Thus, there are things that you can (seemingly) do in Java code that you can't do with reflection because they rely on special behaviours in the compiler that are not replicated in the reflection library. 因此,您可以(看似)在Java代码中执行一些您无法通过反射执行的操作,因为它们依赖于编译器中未在反射库中复制的特殊行为。
Your public static void main( String[] args )
and field private int theAnswer = 42
are in the same class, because of that fact accessDirectly
prints 42 just fine (you have access to field in outer class), but when you are using reflection, you are loading object Class Class Outer
where field private int theAnswer = 42
is private (no access to another class private fields). 你的
public static void main( String[] args )
和field private int theAnswer = 42
属于同一个类,因为accessDirectly
打印42就好了(你可以访问外部类中的字段),但是当你使用反射时,您正在加载对象Class Class Outer
,其中字段private int theAnswer = 42
是私有的(无法访问另一个类私有字段)。 And exception java.lang.IllegalAccessException
is thrown if there are no field.setAccessible( true )
calling. 如果没有
field.setAccessible( true )
调用,则抛出异常java.lang.IllegalAccessException
。
In this example method is calling from the same class, but you are calling it from inner class public static class Inner
. 在此示例中,方法是从同一个类调用,但是您从内部类
public static class Inner
调用它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.