【问题标题】:IllegalAccessError: accessing a protected methodIllegalAccessError:访问受保护的方法
【发布时间】:2010-08-02 09:56:53
【问题描述】:

我有两节课。

A 具有受保护的方法m()aA 的一个实例。

B 类与A 类在同一个包中。

我正在尝试访问a.m(),但我收到了IllegalAccessError...

怎么了?

【问题讨论】:

  • 请制作一个简短但完整的程序来演示该问题。这听起来很奇怪。您是否涉及任何混淆等?

标签: java


【解决方案1】:

编译器应该捕获这样的错误。当您显然在运行时得到这个时,发生了一些奇怪的事情。可能您已经更改了源代码但完全重新编译。

另一个潜在但模糊的问题是通过不同的类加载器加载类。即使包名相同,从不同类加载器加载的类也会在不同的包中(就像不同类加载器加载的同名类会是不同的类一样)。

【讨论】:

    【解决方案2】:

    如果类 A 和 B 由不同的类加载器加载,就会发生这种情况。 jvm 然后认为这些类位于不同的“运行时包”中。引自the jvm specification,第 5.3 节:

    在运行时,类或接口不仅仅由其名称决定,而是由一对:它的完全限定名称和它的定义类加载器决定。每个这样的类或接口都属于一个运行时包。类或接口的运行时包由包名和定义类或接口的类加载器决定。

    在第 5.4.4 节中:

    当且仅当满足以下任一条件时,类或接口 D 才能访问字段或方法 R:

    ...

    R 要么是受保护的,要么是包私有的(即既不是公共的,也不是受保护的,也不是私有的),并且由与 D 相同的运行时包中的类声明。

    【讨论】:

    • 我怀疑这可能会导致我的问题,但不确定第二个类加载器会在堆栈中的哪个位置被拉入或如何调试。但会环顾四周....
    • 我在谷歌上搜索了另一个问题后找到了这个答案,其中我的类位于同一个命名包中,但运行时包不同。这让事情变得更有意义! +1
    【解决方案3】:

    它必须工作,请看下面的例子,它工作得很好:

    package com.stackoverflow;
    
    public class TEST
    {
      static class A {
        protected void m()
        {
          System.out.println("hello from A.m()");
        }
      }
    
      static class B {
    
        public B()
        {
          a.m();
        }
    
        private A a = new A();
      }
    
      /**
       * @param args
       */
      public static void main(String[] args)
      {
        B b = new B();
      }
    }
    

    打印出预期的消息:“hello from A.m()

    "受保护的修饰符指定 该成员只能在内部访问 它自己的包(与 包私有),此外,通过 另一个类的子类 包。”

    Controlling Access to Members of a Class

    【讨论】:

    • “protected 修饰符指定该成员只能在其自己的包中访问(与 package-private 一样),此外,它的类在另一个包中的子类也可以访问。” download.oracle.com/javase/tutorial/java/javaOO/…
    • 或者保留默认访问权限(即没有访问说明符)以允许包访问。
    • 我更改了答案的内容,以前的内容有问题,对此感到抱歉,谢谢@fd;你确定你的 B 类真的和 A 类在同一个包中吗?
    • 内容现在正确、​​有用,但不直接回答问题(可能需要问题中的更多信息)
    • 它应该可以工作;如果不是,那是因为其他原因,例如类加载器问题或其他原因
    【解决方案4】:

    编译器应该捕获这样的错误。当您在运行时得到这个时,发生了一些错误。很可能您已经更改了完全重新编译的源代码。

    它必须有效。这是一个运行示例 -

    **

    • A 类

    **

    package com.test;
    
    public class A {
    
      protected void m(){
      System.out.println("Hi Stackoverflow");
     }
    
    }
    

    **

    • B 类

    **

    package com.test;
    
    public class B{
    
    public static void main(String[] args) {
      A a = new A();
      a.m();
     }
    
    }
    

    打印预期的字符串

    你好 Stackoverflow

    【讨论】:

      猜你喜欢
      • 2020-07-26
      • 2011-08-14
      • 2014-12-19
      • 2012-08-06
      • 2014-12-29
      • 2013-04-06
      • 2014-10-31
      • 1970-01-01
      • 2020-05-02
      相关资源
      最近更新 更多