简体   繁体   English

为什么使用反射访问外部类的私有成员会抛出IllegalAccessException?

[英]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 )抛出IllegalAccessExceptionaccessDirectly打印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代码中执行一些您无法通过反射执行的操作,因为它们依赖于编译器中未在反射库中复制的特殊行为。

You can read more here 你可以在这里阅读更多

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.

相关问题 为什么在使用反射时没有非法访问异常 - why no illegalAccessException on using reflection IllegalAccessException:尝试使用反射访问隐藏的类 - IllegalAccessException: Try to access hidden class using reflection 使用反射访问私有内部类字段 - accessing private inner class field using reflection 关于使用反射的IllegalAccessException - IllegalAccessException on using reflection 访问成员类的私人成员 - accessing private member of member class 使用Java反射从MainActivity类访问私有属性-字段 - Accessing private attributes from MainActivity class using java reflection - Field java匿名类可以访问外部类的私有成员。 为什么此代码无法访问私有数据成员? - java anoymous class can access private member of outer class. Why this code cannot access private data member? 关于访问外部类的私有成员 - Regarding access to private member of outer class java.lang.IllegalAccessException:. 无法使用修饰符“private static”访问类 CrossOrigin 的成员 - java.lang.IllegalAccessException:.cannot access the member of class CrossOrigin with modifiers "private static" jsonobject IllegalAccessException无法使用修饰符“private”访问类java.util.HashMap的成员 - jsonobject IllegalAccessException can not access a member of class java.util.HashMap with modifiers “private”
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM