默认情况下枚举中变量的访问级别是什么

最近我遇到了以下代码:

enum Animals { DOG("woof"), CAT("meow"), FISH("burble"); String sound; Animals(String s) { sound = s; } } class TestEnum { static Animals a; public static void main(String[] args) { System.out.println(a.DOG.sound + " " + a.FISH.sound);//Expected compilation failure } } 

我希望代码无法编译因为这个a.DOG.sound部分。 但令我惊讶的是它没有。 我四处搜索,包括官方文档,以找出访问级别,但一无所获。 是公开的还是默认的

枚举中手动声明的字段的隐式访问级别是package-private ,与普通类中的完全相同。 因此,当且仅当AnimalsTestEnum位于同一个包中时,才能访问您的sound场。


我试图在JLS中为此找到一个可靠的引用,但不幸的是,枚举规则遍布整个地方,被指定为普通类规则的例外,因此规则必须从各个部分组合。 JLS§6.6.1确定可访问性说:

只有在类型可访问且声明成员或构造函数允许访问时,才可访问引用类型的成员(类,接口,字段或方法)或类类型的构造函数:

  • 如果成员或构造函数声明为public ,则允许访问。

    缺少访问修饰符的接口的所有成员都是隐式public

  • 否则,如果成员或构造函数被声明为protected ,则只有在满足以下条件之一时才允许访问:

    • 从包含声明protected成员或构造函数的类的包中发生对成员或构造函数的访问。

    • 访问是正确的,如§6.6.2中所述。

  • 否则,如果使用包访问声明成员或构造函数,则仅当从声明类型的包中进行访问时才允许访问。

    声明没有访问修饰符的类成员或构造函数隐式具有包访问权限。

  • 否则,成员或构造函数被声明为private ,并且当且仅当它发生在包含成员或构造函数声明的顶级类(第7.6节)的主体内时才允许访问。

这意味着类类型( classenum )获得成员隐式具有包访问权限的规则,而接口类型( interface@interface )获得成员隐式公开的规则。

从上面可以看出,“类成员”在其“类”的定义中包含枚举,但确实如此。 由于它们的广泛重叠,JLS组在许多地方枚举了类(并且注释类型同样与接口一起分组)。 JLS§8.9枚举类型说“枚举声明指定一种新的枚举类型,一种特殊的类类型”; 和JLS§8.2class级成员明确指出,“class级成员”一词是指“class级类型”的成员。

但是,枚举确实有两个关于成员可访问性的特殊规则,这些规则未包含在上面引用的部分中:

  1. 枚举常量本身(在您的示例中为DOGCATFISH )可能没有任何显式访问修饰符( JLS§8.9.1 ),并且始终是枚举类型的public static final字段( JLS§8.9.3 ) 。

  2. 枚举构造函数必须是私有的(以防止人们创建额外的常量)并且是隐式私有的( JLS§8.9.2 )。

除了这两个例外,普通类的访问规则适用于枚举。 如果您的Animals枚举是public ,它及其所有常量都可以在包外访问,但sound场是包私有的,除非您明确public声明,否则无法在包外访问。

如果可以导入enum ,则可以访问enum常量

如果enumpackage外可访问(特别是声明为public ),则它的元素也是可访问的,如果没有指定修饰符,它只能在package内访问。 默认情况下,如果enum可访问,则可以访问enum常量,这意味着默认情况下这些常量是public static final

我希望代码无法编译因为这个a.DOG.sound部分。 但令我惊讶的是它没有。

它将与任何其他变量在任何类中的行为相同,如果没有默认修饰符,它只能在包内访问。