【问题标题】:Accessing private inner class in the same package访问同一个包中的私有内部类
【发布时间】:2011-08-22 12:18:33
【问题描述】:

我有两个编译单元:

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”。如果它们位于不同的包中,则会引发 IllegalAccessException。

据我了解,引发异常是因为 CallingClass 无法调用私有 InnerClass 方法。但我不明白的是为什么它允许在同一个包中? InnerClass 不受包保护。 Private 不应该在 OuterClass 之外可见,即使它在同一个包中。我是不是理解错了?

【问题讨论】:

  • 您命名为InnerClass 的类不是内部类。它实际上是一个静态嵌套类。 (在 Java 中,嵌套类有两种:静态和内部。)您提出了一个很好的问题,但它与内部类没有任何关系,所以我建议您重命名 InnerClass 以及标题问题。

标签: java reflection visibility inner-classes


【解决方案1】:

内部类的javap 签名:

class modifiers.OuterClass$InnerClass extends java.lang.Object{
    final modifiers.OuterClass this$0;
    public java.lang.String test();
}

当涉及到字节码(即运行时)时,没有私有类之类的东西。这是由编译器维护的虚构。对于反射 API,有一个带有公共成员方法的包可访问类型。

实际的访问修饰符定义在JVM spec:

Flag Name      Value   Interpretation
ACC_PUBLIC     0x0001  Declared public; may be accessed from outside its package.
ACC_FINAL      0x0010  Declared final; no subclasses allowed.
ACC_SUPER      0x0020  Treat superclass methods specially when invoked by the
                       invokespecial instruction.
ACC_INTERFACE  0x0200  Is an interface, not a class.
ACC_ABSTRACT   0x0400  Declared abstract; may not be instantiated. 

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 你是对的。但是为什么我可以在课堂之外访问它呢?
    • 看起来反射系统出于未知原因允许这样做。我认为硬编码的方法调用是不可能的。
    • 这个答案并不完全准确。 Java 语言(及其编译器)会产生一些编译后不成立的错觉。反射 API 对生成的字节码进行操作,并且不知道任何被编译器清除的内容。
    猜你喜欢
    • 2011-02-17
    • 1970-01-01
    • 2011-02-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多