Java枚举变量是静态的吗?

7
public enum Operations {

    SINGLE,
    MULTIPLE;

    private Type operation;

    public void setOperation(Type operation) {
        this.operation = operation;
    }

    public Type getOperation() {
        return operation;
    }

    public static void main(String[] args) {
        Operations oper1 = Operations.SINGLE;
        oper1.setOperation(Type.GET);

        Operations oper2 = Operations.SINGLE;
        oper2.setOperation(Type.POST);
        System.out.println(oper1.getOperation());
        System.out.println(oper2.getOperation());
    }
}

enum Type {
    POST,
    GET;
}

在上述代码中,操作的值会同时改变 Operations 的两个实例。如何创建两个具有不同操作类型的 Operations.SINGLE 实例?

1
如果您告诉我们标准输出打印了什么内容,那么您的问题会更容易理解。(我假设它会打印两次“POST”?) - Duncan Jones
SINGLE 相当于 public static final Operations SINGLE = new Operations("SINGLE", 0)。 - Blackbelt
6个回答

16

是的,实例隐式地具有staticfinal属性。这意味着代码是不明智的。想象一下两个线程同时调用SINGLE.setOperation(Type);你将无法确定你正在调用什么。

来自Java语言规范,第8.9节

枚举类型(§8.9)不能声明为抽象的;这样做会导致编译时错误。

除非枚举类型至少包含一个带有类主体的枚举常量,否则枚举类型是隐式的 final。

显式地声明枚举类型为 final 是编译时错误。

嵌套枚举类型是隐式的 static。可以显式地将嵌套枚举类型声明为 static。

在下一节中:

枚举类型的主体可以包含枚举常量。枚举常量定义了枚举类型的一个实例。 由于每个枚举常量只有一个实例,如果已知至少其中一个引用了枚举常量,则可以使用“==”运算符代替equals方法来比较两个对象引用。

11
我如何拥有两个不同操作类型的 Operations.SINGLE 实例?
“枚举”(enum)的基本思想是,每个成员只有一个实例。这使得你可以安全地比较它们是否相等,而不必担心其他地方创建了另一个“SINGLE”或“MULTIPLE”。
如果您想要多个“SINGLE”实例,请将其作为“class”而不是“enum”。您将“enum”变成可变的事实间接地指向了同样的方向:在您的情况下使用“enum”是错误的选择。

10

枚举实例是“静态的”(即像静态变量一样),但不是不可变对象

所有线程都看到由枚举名称引用的相同对象-它们就像单例,JVM有铁一般的保证只有一个枚举实例。更改枚举的字段会使所有人都发生变化。

在枚举中将字段设置为final并将它们设置为不可变是良好的实践。


2
我晚了一年半。但是我看到这个问题并没有得到真正的回答。
解决方案将使用一个类而不是枚举,该类具有这两个枚举作为其字段:
class Operation {
    Quantity quantity;
    Type type;
    Operation(Quantity quantity, Type type) {
        this.quantity = quantity;
        this.type = type;
    }
}

当然,你可以使用枚举而不是类。然后你需要枚举所有的组合:
enum Operation {
    SINGLE_GET(Quantity.SINGLE, Type.GET)
    SINGLE_POST(Quantity.SINGLE, Type.POST)
    MULTIPLE_GET(Quantity.MULTIPLE, Type.GET)
    // ... more options
    // contents same as in class Operation, constructor private by default
}

这两种方法都是有效的,有时您确实想要枚举所有组合,但大多数情况下,您应该坚持使用“class”方法。

为简洁起见,我没有定义枚举“Quantity”和“Type”,它们只是简单的枚举。


0

主方法的第四行有一个错误。

oper1.setOperation(Type.POST);

应该是

oper2.setOperation(Type.POST);

代码中有拼写错误。 - Optional

0

是的,enum的所有元素都是static final constant

然而,正如darijan在另一个回答中提到的那样,您的程序存在逻辑错误。


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