我什么时候应该使用final关键字而不是枚举?

时间:2015-04-06 14:58:56

标签: java enums final

我的代码中有以下字段:

private static final int NUM_NANOSECONDS_IN_MILLISECOND = 1000000;

有人告诉我,为了类型安全,我应该使用枚举。这不是我熟悉的。但如果是这种情况,我不知道何时在某个字段上使用final关键字是合适的。

我什么时候应该使用final关键字而不是enums?

5 个答案:

答案 0 :(得分:6)

使用枚举可避免使用int,而不是final。使用专用枚举提供类型安全性,因此您可以使用更清晰的方法签名并避免错误。 final用于防止一旦设置更改值,并且无论变量的类型如何,都是一种良好的做法。

在这种情况下,我不确定枚举给你的价值。 NUM_NANOSECONDS_IN_MILLISECOND似乎不应该是专用类型,正如@BoristheSpider建议的那样,你根本不需要这个字段。也许你的同事建议使用单元的枚举(例如NANOSECONDMILLISECOND等),而不是像这样存储比率。在这种情况下,现有的TimeUnit枚举绝对是您的朋友。

答案 1 :(得分:6)

常量只是具有名称的常量。 枚举是具有值的文字常量。我解释一下......

考虑:

public final static int NORTH = 0;
public final static int SOUTH = 1;
public final static int EAST = 2;
public final static int WEST = 3;

public enum Direction {
    NORTH, SOUTH, EAST, WEST
}

从可读性的角度来看,它看起来有点相似:

if(direction == NORTH)

或使用枚举:

if(direction == Direction.NORTH)

可能出现问题的是最终常数,你也可以

if(direction == 0)

现在,即使它做同样的事情,也很难理解代码。使用枚举,你就是不能这样做,所以它会让问题发生。

同样,当期望方向作为方法参数时:

最终静态:

public void myMethod(int direction)

并使用枚举:

public void myMethod(Direction direction)

它更清晰,问题机会也更少。

这只是一个开始。枚举实际上可以有方法帮助您更好地管理它们包含的信息。阅读here以获得清晰的解释。

示例:

public enum Direction {
    NORTH (0, 1),
    SOUTH (0, -1),
    EAST (1, 0),
    WEST (-1, 0)

    private int xDirection, yDirection;

    Direction(int x, int y) {
        this.xDirection = x;
        this.yDirection = y;
    }

    public Vector2D getTranslation() {
        return new Vector2D(this.xDirection, this.yDirection);
    }
}

然后在你的代码中:

public void moveThePlayer(Player p, Direction d) {
    p.translate(d.getTranslation());
}

moveThePlayer(p, Direction.NORTH);

这对final static来说真的很难。或者至少,它变得非常难以理解。

所有这一切都说,你在那里工作的特殊情况,如果只有一个数字常数值,我保持最后的静态。如果有单个值,则无需使用枚举。

答案 2 :(得分:4)

老实说,这取决于你需要什么。 enum正如其名称所示,代表枚举

枚举有多个元素,如此

public enum Colors {
    CYAN, MAGENTA, YELLOW, BLACK
}

你甚至可以给他们数值左右!因为枚举很酷。

public enum RGBColors {
    RED(0xFF0000), GREEN(0x00FF00), BLUE(0x0000FF);

    private int hexacolor;

    private RGBColors(int hexacolor) {
        this.hexacolor = hexacolor;
    }

    public int getColorValue() {
        return hexacolor;
    }
}

你的情况只是一个数值常数。 单个数字常量。

public static final long SUCH_NUMERICAL_VALUE = 12367160L;

这只是一个常数。这不是枚举。也没有理由将它作为枚举,因为您只是将它用作数字。

enum的最大优势(在我看来)是你可以迭代其类型的每个元素。

for(RGBColors rgbColor : RGBColors.values()) {
    ... //do things with rgbColor for each of them
}

public static final int无法做到这一点。我甚至在这里围绕一堆enum属性编写了一个public static final包装器,因为这个问题:https://stackoverflow.com/a/28295134/2413303

更重要的是,您可以轻松阅读什么价值代表什么,而不必深入到源:

RGBColors red = RGBColors.RED;

现在让我们看一下int:

int red = RGBColors.RED;

我可以说

int red = 0; //red color

谁会告诉我们以后会发生什么?谁知道!

无论如何,简短的回答是,枚举非常棒,当您指定枚举时,即多个元素(或者您正在创建) enum singletons),这些元素需要有额外的方法或属性。

public enum MySingleton { //this is an enum singleton
    INSTANCE;

    public void doThings() {
        System.out.println("hello!");
    }
}

MySingleton.INSTANCE.doThings(); //hello!

常量(public static final)非常适合使用它们:常量

答案 3 :(得分:3)

我想说枚举的一般用例是当你有一小组有限的值组成一些你正在建模的集合时,你将枚举每一个。它们还可以帮助确保应包含其中一个值的字段不包含其他值。

在这种情况下,似乎都不适用。你也可以拥有NUM_NANOSECONDS_IN_MICROSECONDNUM_NANOSECONDS_IN_SECONDNUM_NANOSECONDS_IN_PI_MILLISECONDS等等,而且你不会枚举每一个。此外,您可能不会将存储这些值的变量限制为已定义常量的值。

答案 4 :(得分:1)

编写源代码时,最好尽可能依赖编译器来帮助您找到逻辑错误。一种方法是使用变量和常量类型,这样如果对方法使用了错误的常量,编译器会将此标记为错误。

建议并非真正使用finalenum,因为这些实际上是两种不同的编程概念。相反,它使用enum来创建显式且唯一的类型,而不是使用int,而int则不那么明确且独特。如果您使用int作为函数的方法签名的一部分,该函数应该花费几纳秒,那么编译器将接受任何enum值。如果您改为使用enum,则只允许final中指定的值。使用其他任何东西都会导致编译器发出错误。

enum关键字是一种确保不能覆盖或修改变量的方法,以便变量充当常量。 wikipedia article on final

enum中指定的值是常量,因此您可以选择使用您拥有的值,常量,还是使用enum常量,但使用enum将提供来自编译器的安全检查,以便只能在方法调用或变量赋值中使用enum的指定值纳秒。

这是来自该堆栈溢出的explanation of final with additional linksJava method keyword final and its use还提供了一些其他信息。

有关{{1}}的一些解释,请参阅What is the purpose of Enum