Java 访问同一包中的私有内部类

Java 访问同一包中的私有内部类,java,reflection,visibility,inner-classes,Java,Reflection,Visibility,Inner Classes,我有两个汇编单元: public class OuterClass{ private static class InnerClass{ public String test(){ return "testing123"; } } public static void main( String[] args ){ new CallingClass().test( new InnerClass()

我有两个汇编单元:

public class OuterClass{

    private static class InnerClass{

        public String test(){
            return "testing123";
        }
    }

    public static void main( String[] args ){
        new CallingClass().test( new InnerClass() );
    }
}


public class CallingClass{

    public void test( Object o ){
        try{
            Method m = o.getClass().getMethod( "test" );
            Object response = m.invoke( o );
            System.out.println( "response: " + response );
        }
        catch( Exception e ){
            e.printStackTrace();
        }
    }
}
如果它们在同一个包中,则所有内容都有效,并打印“response:testing123”。如果它们在单独的包中,则抛出IllegaAccessException


据我所知,抛出异常是因为CallingClass无法调用私有的InnerClass方法。但我不明白的是,为何在同一个方案中允许这样做?InnerClass不受包保护。Private不应在OuterClass外部可见,即使它位于同一个包中。我理解错了吗?

私有访问修饰符比包一更强大(即在Java中根本没有访问修饰符)。因此,类的私有元素(无论是字段、方法还是内部类)只能在该类中访问。

内部类的签名:

class modifiers.OuterClass$InnerClass extends java.lang.Object{
    final modifiers.OuterClass this$0;
    public java.lang.String test();
}
当涉及字节码(即运行时)时,没有私有类。这是由编译器维护的虚构。对于反射API,有一个带有公共成员方法的包可访问类型

实际访问修饰符在中定义:

标志名称值解释
ACC_PUBLIC 0x0001已声明为PUBLIC;可以从其包外部访问。
ACC_FINAL 0x0010宣布为最终版本;不允许使用子类。
ACC_SUPER 0x0020在被
调用特殊指令。
ACC_接口0x0200是一个接口,而不是一个类。
ACC_摘要0x0400声明摘要;可能不会被实例化。

你说得对。但是为什么我可以在课堂之外访问它呢?看起来反射系统出于未知的原因允许这样做。我认为硬编码方法调用是不可能的。这个答案并不完全准确。Java语言(及其编译器)产生了一些编译后无法保持的幻觉。反射API对生成的字节码进行操作,并且不知道编译器会清除任何内容。您命名为
InnerClass
的类不是内部类。它实际上是一个静态嵌套类。(在Java中,嵌套类有两种:静态类和内部类。)您提出了一个很好的问题,但它与内部类无关,因此我建议您重命名
InnerClass
,以及问题的标题。