鉴于下面的代码示例,为什么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"
根据this SO answer,我希望它可以正常工作,因为访问确实发生了“(...)来自允许访问它的类”。
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 );
}
}
答案 0 :(得分:2)
“为什么”这样的问题可能很难回答 - 有很多层“为什么”,包括为什么设计师会选择这样做? 规范的哪个部分允许这样做? 底层技术细节是什么?
我会回答其中的最后一个,但我不确定这是不是你想要的。
Java运行时(JVM,安全模型等)对内部类很不了解。在大多数情况下,它们是语言问题。
其中一个后果是编译器使用一些隐藏的技巧来允许内部/外部类访问彼此的私有成员,即使运行时通常不允许它。
其中一个技巧是你的accessDirectly
方法实际上并没有直接访问该字段。编译器在外部类上添加一个隐藏方法,返回值theAnswer
。
字段(theAnswer
)仍然是私有的,就运行时安全模型而言,无法在拥有(外部)类之外访问。
因此,您可以(看似)在Java代码中执行一些您无法使用反射执行的操作,因为它们依赖于编译器中未在反射库中复制的特殊行为。
您可以阅读更多here
答案 1 :(得分:0)
您的private int theAnswer = 42
和字段accessDirectly
属于同一个类,因为这个事实Class Outer
打印42就好了(您可以访问外部类中的字段),但是当您是使用反射,您正在加载对象Class private int theAnswer = 42
,其中字段java.lang.IllegalAccessException
是私有的(无法访问其他类私有字段)。如果没有field.setAccessible( true )
来电,则会引发异常public static class Inner
。
在this示例中,方法是从同一个类调用,但是您是从内部类<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.5.RELEASE</version>
<relativePath></relativePath>
</parent>
调用它。