我们假设我们有一个班级:
public class SomeClass {
protected SomeClass () {
}
}
在位于不同包中的MainClass
中,我尝试执行两行:
public static void main(String[] args) {
SomeClass sac1 = new SomeClass();
SomeClass sac2 = new SomeClass() {};
}
由于protected
构造函数,在这两种情况下我都希望程序失败。令我惊讶的是,匿名初始化工作正常。有人可以解释一下为什么第二种初始化方法可以吗?
答案 0 :(得分:9)
您的匿名课程
SomeClass sac2 = new SomeClass() {};
基本上变成了
public class Anonymous extends SomeClass {
Anonymous () {
super();
}
}
构造函数没有访问修饰符,因此您可以在同一个包中无问题地调用它。您还可以调用super()
,因为可以从子类构造函数访问protected
父构造函数。
答案 1 :(得分:3)
第一行失败,因为SomeClass
的构造函数是protected
而MainClass
不在SomeClass
的包中,并且它不是子类{{1 }}
第二行成功,因为它正在创建MainClass
的匿名子类。这个匿名内部类是SomeClass
的子类,因此它可以访问SomeClass
的{{1}}构造函数。此匿名内部类的默认构造函数隐式调用此超类构造函数。
答案 2 :(得分:2)
中的那两个小括号
SomeClass sac2 = new SomeClass() {};
在Java中调用了很多自动行为。以下是执行该行时会发生的情况:
SomeClass
的匿名子类。public
super()
(这是no-arg构造函数总是首先执行的操作)。new
命令调用此匿名子类的无参构造函数,并将结果分配给sac2
。 SomeClass
的匿名子类中的默认无参数构造函数可以访问protected
的{{1}}构造函数,因为匿名子类是SomeClass
的后代,所以对SomeClass
的调用有效。 super()
语句调用此默认的无参数构造函数,该构造函数具有new
可见性。
答案 3 :(得分:0)
你的行
SomeClass sac2 = new SomeClass() {};
创建一个扩展SomeClass
的新类的实例。由于SomeClass
定义了一个没有参数的受保护构造函数,因此子类可以在它自己的构造函数中隐式调用它,这在这一行中发生。