默认情况下,枚举中的变量访问级别是多少

时间:2015-07-31 05:02:48

标签: java enums

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

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在内的所有内容,以找出访问级别,但一无所获。是公开还是默认

2 个答案:

答案 0 :(得分:6)

  

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

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

  

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

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

答案 1 :(得分:5)

枚举中手动声明的字段的隐式访问级别为 package-private ,与普通类中的完全相同。因此,当且仅当soundAnimals位于同一个套餐中时,您的TestEnum字段才可访问。

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

  

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

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

         

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

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

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

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

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

         

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

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

  •   

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

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

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

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

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

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