【问题标题】:Instantiate an inner class inherited with protected access specifier实例化使用受保护的访问说明符继承的内部类
【发布时间】:2015-08-25 14:52:24
【问题描述】:

我想从 Bruce Eckel 的关于内部类的 TIJ 中做以下练习:

Create an interface with at least one method, in its own package.
Create a class in a separate package. Add a protected inner class
that implements the interface. In a third package, inherit from
your class and, inside a method, return an object of the protected
inner class, upcasting to the interface during the return.

这是我的实现:

首先,界面:

package workers;

public interface Employable {
  void work();
}

那么,有一个实现接口的内部类的类:

package second;

import workers.Employable;

public class WorkersClass {
    protected class Worker implements Employable {
        @Override
        public void work() {
            System.out.println("Hello, I'm a worker!");
        }
    }
}

最后是继承的类:

package third;

import second.WorkersClass;
import workers.Employable;

public class Third extends WorkersClass {
    Employable getWorker() {
        return new Worker();//the line is reported to be incorrect
    }
}

IDEA 在getWorker 中用Worker() 划线,并建议将Worker 类设为public。但为什么?它受到保护,这就是为什么WorkersClass 的继承者可以在他们的方法中实例化Worker 类的原因。我是不是误会了什么?

【问题讨论】:

    标签: java inheritance inner-classes


    【解决方案1】:

    问题不在于访问说明符。

    当你没有在类中提供任何构造函数时,编译器会自动为你插入一个默认的、无参数的构造函数

    在这种情况下,情况并非如此。因为编译的内部类没有得到默认构造函数,因为它被编译为outer$inner,而对于inner,编译器没有提供默认构造函数。

    手动提供默认的no org constructor,看看它的神奇之处:)

    package second;
    
    import workers.Employable;
    
    public class WorkersClass {
        protected class Worker implements Employable {
    
    
            public Worker() {
                // TODO Auto-generated constructor stub
            }
    
            @Override
            public void work() {
                System.out.println("Hello, I'm a worker!");
            }
        }
    }
    

    【讨论】:

      【解决方案2】:

      修改 WorkersClass

      public class WorkersClass {
        protected class Worker implements Employable {
      
          public Worker(){}
      
          @Override
          public void work() {
              System.out.println("Hello, I'm a worker!");
          }
        }
      }
      

      【讨论】:

      • 正确答案。但是为什么呢?
      • 隐式默认构造函数可见性与类可见性相同,因此在此类情况下,它将被“保护”。第三是扩展 WorkerClass,而不是 Worker
      • 我没有足够的声誉来评论您的答案,但是,这是一个可见的问题。
      【解决方案3】:

      您的Third 类继承WorkersClass Worker

      Java 并没有真正考虑内部类,它是 Java 1.1 中引入的一个简单的 hack。编译器在类WorkersClass“外部”生成类Worker,但在同一个包中。
      这就是为什么,为了从Third 方法实现一个新的Worker 实例,您需要向Worker 添加一个公共构造函数:

      protected class Worker implements Employable {
      
        public Worker(){
        }
      
        @Override
        public void work() {
          System.out.println("Hello, I'm a worker!");
        }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-05-24
        • 1970-01-01
        • 2013-03-02
        • 2015-05-03
        • 2018-10-21
        • 2019-05-16
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多