实例化一个内部 class 继承与受保护的访问说明符

Instantiate an inner class inherited with protected access specifier

我想根据 Bruce Eckel 的 TIJ 对内部 classes 进行以下练习:

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();
}

然后,一个 class 和一个内部 class 实现接口:

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!");
        }
    }
}

最后是继承的class:

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 class public。但为什么?它受到保护,这就是 WorkersClass 的后继者可以在其方法中实例化 Worker class 的原因。我是不是误会了什么?

修改 WorkersClass

public class WorkersClass {
  protected class Worker implements Employable {

    public Worker(){}

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

问题不全在于访问说明符。

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

在这种情况下,情况并非如此。因为编译后的内部 class 没有获得默认构造函数,因为它被编译为 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!");
        }
    }
}

您的 Third class 继承 WorkersClass Worker.

Java 并没有真正考虑内部 classes,它是 Java 1.1 中引入的一个简单 hack。编译器生成 class Worker "outside" of class WorkersClass,但在同一个包中。
这就是为什么,为了从 Third 方法实现一个新的 Worker 实例,您需要向 Worker:

添加一个 public 构造函数
protected class Worker implements Employable {

  public Worker(){
  }

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