【问题标题】:What is the access level of variables in enums by default [duplicate]默认情况下枚举中变量的访问级别是多少[重复]
【发布时间】:2015-10-22 16:11:44
【问题描述】:

最近我遇到了以下一段代码:

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 部分而无法编译。但令我惊讶的是,事实并非如此。我四处搜索,包括official documentation 以找出访问级别,但一无所获。是 public 还是 default

【问题讨论】:

  • 适用正常的可访问性访问规则。
  • 好问题。在这种情况下,String sound 缺少访问修饰符,这使其具有默认可见性。这意味着它对同一包中的所有其他类都是可见的。查看this chart,特别是int i 行。

标签: java enums


【解决方案1】:

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


我试图在 JLS 中找到一个可靠的引用,但不幸的是枚举规则分散在各处,被指定为普通类规则的例外,因此必须从碎片中组装规则。 JLS §6.6.1 Determining Accessibility 说:

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

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

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

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

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

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

  • 否则,如果成员或构造函数声明为具有包访问权限,则仅当访问发生在声明类型的包内时才允许访问。

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

  • 否则,成员或构造函数被声明为 private,并且当且仅当它出现在包含成员或构造函数。

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

从上面看,“类成员”在其“类”的定义中包含枚举并不是很明显,但确实如此。由于它们的广泛重叠,JLS 在许多地方将枚举与类分组(并且注释类型同样与接口分组)。 JLS §8.9 Enum Types 说“一个枚举声明指定了一个新的枚举类型,一种特殊的类类型”; JLS §8.2 Class Members 清楚地表明“类成员”一词是指“类类型”的成员。

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

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

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

除了这两个例外,普通类的访问规则适用于枚举。如果你的Animals 枚举被设为public,它和它的所有常量都可以在包外访问,但是sound 字段是包私有的,除非你明确声明它public,否则不能在包外访问。

【讨论】:

  • 我认为这个答案值得被接受。感谢“挖掘”
【解决方案2】:

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

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

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

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

【讨论】:

  • 删除了我对你有利的回答。 enum 公开是很重要的一点,很多人都忽略了这一点。 +1
猜你喜欢
  • 2011-06-25
  • 2013-04-09
  • 2018-09-16
  • 2011-10-14
  • 2012-11-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多