自从什么时候开始枚举类型的构造函数默认访问修饰符是私有的?

3
enum构造函数的默认访问修饰符“private”从一开始就存在,还是在Java 8中更改了?如果更改了,那么没有访问修饰符的构造函数声明的默认访问修饰符是什么? (我猜它是默认的(包可访问),就像其他Java类的构造函数一样。)我找到了一些相关文档,但找不到确切的答案。这是我找到的,
  1. Java8 JLS 8.9.2,在枚举声明中,没有访问修饰符的构造函数声明为private。
  2. Java7 JLS 8.9.2,如果枚举类型没有构造函数声明,则会自动提供一个不带参数的私有构造函数(以匹配隐式空参数列表)。

我认为这是一个有效的问题,但我只是好奇:为什么这个构造函数的确切访问权限很重要呢?我不认为我的问题的答案与你的相关,这只是我的好奇心。 - Joachim Sauer
我刚在JLS 7 § 8.8.3中发现了等效规则(只是在另一个位置):“如果未为枚举类型的构造函数指定访问修饰符,则构造函数为私有。” 同样的规则可以追溯到至少Java 6 - Joachim Sauer
感谢提供JLS7文档!直到昨天,我一直在显式地使用“private”访问修饰符来调用枚举构造函数。因为我知道如果没有访问修饰符, 默认访问范围是“package”,而枚举构造函数应该是“private”。但是我发现默认值是private,所以没必要显式地使用“private”了!所以我想知道枚举构造函数的默认访问修饰符自从何时开始是private的。 - Somin Lee
1个回答

5
自从枚举类型被引入以来,其构造函数的默认访问修饰符一直是"private"。这也正是它们存在的原因:不能创建新的枚举类型。在 openjdk16 的 javac 中,枚举类型的构造函数不能为非私有的。
> cat Test.java
public enum Test {
  FOO, BAR;
  public Test() {}
}
> javac Test.java
Test.java:3: error: modifier public not allowed here

我们来试一下Java6(是的,我手头有javac6,并且可以在新的Java上运行它)。

> java -jar javac6.jar -bootclasspath openjdk6-rt.jar Test.java
Test.java:3: error: modifier public not allowed here

所以,这个错误已经持续了两个十年。

让我们来检查javac6中的访问级别!

> cat Test.java
public enum Test {
    FOO, BAR;
    Test() {}
}
> java -jar javac6.jar -bootclasspath openjdk6-rt.jar Test.java
> javap -c -private Test
.... lots of decompiled bytecode

private Test();
    Code:
       0: aload_0
       1: aload_1
       2: iload_2
       3: invokespecial #18                 // Method java/lang/Enum."<init>":(Ljava/lang/String;I)V
       6: return

... more decompiled bytecode

私有性质的特征是始终存在的,也将一直存在。这就好比在问:“圆曾经拥有过角吗?”

答案是:不曾拥有。如果圆拥有角,那么它就不再被认定为圆。带有公共构造函数的枚举类型并非真正的枚举类型。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接