使用受保护的构造函数匿名初始化 class

Anonymous initialization of class with protected constructor

假设我们有一个 class:

public class SomeClass {    
    protected SomeClass () { 
    }
}

在位于不同包中的 MainClass 中,我尝试执行两行:

public static void main(String[] args) {
    SomeClass sac1 = new SomeClass(); 
    SomeClass sac2 = new SomeClass() {}; 
}

由于 protected 构造函数,在这两种情况下我都希望程序失败。令我惊讶的是,匿名初始化工作正常。有人能解释一下为什么第二种初始化方法可以吗?

第一行失败,因为SomeClass的构造函数是protected,而MainClass不在SomeClass的包中,也不是子classing MainClass.

第二行成功,因为它正在创建 SomeClass 的匿名子 class。这个匿名内部 class subclass 是 SomeClass,所以它可以访问 SomeClassprotected 构造函数。此匿名内部 class 的默认构造函数隐式调用此超级 class 构造函数。

你的匿名class

SomeClass sac2 = new SomeClass() {}; 

基本变成了

public class Anonymous extends SomeClass {
    Anonymous () {
        super();
    }
}

构造函数没有访问修饰符,因此您可以从同一个包中毫无问题地调用它。您还可以调用 super(),因为可以从子class 构造函数访问 protected 父构造函数。

你的线路

SomeClass sac2 = new SomeClass() {};

创建一个扩展 SomeClass 的新 class 的实例。由于 SomeClass 定义了一个不带参数的受保护构造函数,子 class 可能会在自己的构造函数中隐式调用它,这发生在这一行中。

中的那两个小括号
SomeClass sac2 = new SomeClass() {};

在 Java 中调用大量自动行为。这是执行该行时发生的情况:

  1. 已创建 SomeClass 的匿名子class。
  2. 那个匿名子class被赋予一个默认的无参数构造函数,就像任何其他没有无参数构造函数声明的Javaclass一样。
  3. 默认的无参数构造函数定义可见性 public
  4. 默认的无参数构造函数被定义为调用 super()(这是无参数构造函数总是首先执行的操作)。
  5. new命令调用这个匿名子class的无参数构造函数并将结果赋值给sac2.

SomeClass 的匿名子 class 中的默认无参数构造函数可以访问 SomeClassprotected 构造函数,因为匿名子class 是 SomeClass 的后代,因此对 super() 的调用是有效的。 new 语句调用此默认无参数构造函数,它具有 public 可见性。