2011-08-30 98 views
11

所以,我有我的枚举的Java公共枚举法的目的

public enum Sample { 
    ValueA{ 
     @Override 
    public String getValue(){ return "A"; } 
}, 
ValueB{ 
    @Override 
    public String getValue(){ return "B"; } 

    public void doSomething(){ } 
}; 
abstract public String getValue(); 
}; 

,我有一些其他的代码试图利用枚举。

Sample.ValueB.doSomething(); 

这似乎应该是有效的,但会产生错误“方法doSomething()未定义类型Sample”。相对于

Sample value = Sample.ValueB; 
value.doSomething(); 

它产生相同的错误,似乎是合理的。

我假设有一个合理的答案,为什么第一个不起作用,它涉及到两个例子在引擎盖下等价。我希望有人能指出我为什么这样的文档。

+0

如果你想说出什么错误,那真的会有帮助... –

+0

不应该调用'Sample.doSomething()'吗? – nfechner

+2

@ nfechner ..'doSomething()'方法不是静态的。 –

回答

15

类型的“场”的ValueASample。这意味着您只能调用Sample提供的ValueA上的方法。从JLS §8.9.1. Enum Constants:在这些类机构宣布

实例方法可以封闭枚举类型外部调用只有当它们覆盖在封闭枚举类型访问的方法。

更重要的是:从设计的角度enum值应是均匀的:如果一些操作是可能与一个特定的值,那么它应该是可能的所有的值(尽管它可能导致正在执行不同的代码)。

10

基本上编译时类型的Sample.ValueB仍然样品,即使执行时间类型的值将是ValueB。所以你的两段代码是相同的 - 客户端不会看到只在的枚举值的中出现的“额外”方法。

可以有效地想到枚举作为声明场这样的:

public static final Sample ValueB = new Sample() { 
    @Override 
    public String getValue(){ return "B"; } 

    public void doSomething(){ } 
}; 
4

当你写

enum Sample 
{ 
    Value{ 
     public void doSomething() 
     { 
       //do something 
     } 
    }; 
} 

你没有创建Sample枚举,而一个匿名子类enum Sample的一个实例的实例。这就是为什么方法doSomething()未定义。

更新:

试试这个

System.out.println(Sample.ValueB.getClass().getName()); 

打印Sample$2

这意味着,即使你有方法doSomething()Sample$2实例,你必须:这可如下证明名称为ValueB,您是通过Sample类型的超级参考来引用它,因此只有类Sample中定义的那些方法将是在编译时可见。

您可以在运行时通过反射调用doSomething()

+1

更重要的是:“字段”值的类型**仍然是** Sample和* Not *'Sample $ 1'。 –

3

public void doSomething(){ }将与private void doSomething(){ }具有相同的效果。

doSomething()在ValueB之外不可见,除非您将doSomething()添加到Sample

每个Sample值的类型为Sample,因此对于不同的值(从外部角度)不能有不同的方法集。

+0

警告:如果样本类有一个类体,那么'Sample' * values * ** do **会有更具体的类型。 'Sample' *字段*只有'Sample'类型。 –

+0

@Joachim:当然,但这些特定类型是Sample的匿名子类,所以“外部”只能使用Sample定义的接口。我没有让自己清楚 - 对不起。 –