什么时候应该使用 final 关键字而不是枚举?
When should I use the final keyword instead of enums?
我的代码中有以下字段:
private static final int NUM_NANOSECONDS_IN_MILLISECOND = 1000000;
有人告诉我,为了类型安全,我应该为此使用枚举。这不是我熟悉的东西。但如果是这种情况,我不知道什么时候才适合在字段上使用 final 关键字。
什么时候应该使用 final 关键字而不是枚举?
使用枚举可以避免使用 int
,而不是 final
。使用专用枚举提供类型安全,因此您可以拥有更清晰的方法签名并避免错误。 final
用于防止在设置后更改值,并且无论变量的类型如何,这通常都是一种好的做法。
但是在这种情况下,我不确定枚举能给您带来什么价值。 NUM_NANOSECONDS_IN_MILLISECOND
似乎不应该是专用类型,正如@BoristheSpider 所建议的那样,您根本不需要这个字段。也许您的同事建议为单位使用枚举(例如 NANOSECOND
、MILLISECOND
等)而不是像这样存储比率。在那种情况下,现有的 TimeUnit
枚举绝对是你的朋友。
常量就是有名称的常量。
枚举是具有值的文字常量。我解释...
考虑:
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
很难做到这一点。或者至少,它变得非常不可读。
综上所述,对于您正在处理的特定情况,如果只有一个数字常量值,我会保持最终静态。如果只有一个值,就没有必要使用枚举。
我想说的是枚举的一般用例是当你有一个小的有限值集,这些值形成了你正在建模的某个集合并且你将枚举每个值。它们还可以帮助确保应包含这些值之一的字段不包含其他值。
在这种情况下,两者似乎都不适用。您也可以使用 NUM_NANOSECONDS_IN_MICROSECOND
、NUM_NANOSECONDS_IN_SECOND
、NUM_NANOSECONDS_IN_PI_MILLISECONDS
等,您不会一一列举。此外,您将要存储这些值的变量似乎不应该限于定义的常量的值。
老实说,这取决于您的需要。 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
做到这一点。由于这个问题,我什至在这里围绕一堆 public static final
属性写了一个 enum
包装器:
更重要的是,您无需深入源代码就可以轻松阅读什么值代表什么:
RGBColors red = RGBColors.RED;
现在让我们用 int 看看这个:
int red = RGBColors.RED;
我只能说
int red = 0; //red color
谁来告诉我后来的事呢?谁知道呢!
Anyways,简短的回答是,enums 在指定 enumerations[=59= 时非常有用],又名多个元素(或者您正在创建枚举单例),并且这些元素需要具有额外的方法或属性。
public enum MySingleton { //this is an enum singleton
INSTANCE;
public void doThings() {
System.out.println("hello!");
}
}
MySingleton.INSTANCE.doThings(); //hello!
常量 (public static final
) 在您使用它们时非常有用:常量.
在编写源代码时,最好尽可能依靠编译器来帮助您发现逻辑错误。一种方法是使用变量和常量类型,这样如果您对方法使用了错误的常量,编译器会将其标记为错误。
建议并不是关于使用 final
与 enum
,因为它们实际上是两个不同的编程概念。它使用 enum
来创建一个显式和唯一的类型,而不是使用 int
来创建一个显式和唯一性低得多的类型。如果您将 int
用作本应花费纳秒的函数的方法签名的一部分,那么编译器将接受任何 int
值。如果您改为使用 enum
,则仅允许 enum
中指定的那些值。使用其他任何东西都会导致编译器发出错误。
final
关键字是一种确保变量不能被覆盖或修改的方法,这样变量就像常量一样。 wikipedia article on final.
enum
中指定的值是常量,因此您可以选择使用现有的常量,或使用 enum
,常量,但是使用 enum
将提供来自编译器的安全检查,以便只有 enum
的指定值可以用于纳秒级的方法调用或变量赋值。
这里有一个explanation of final
with additional links from that stack overflow. Java method keyword final and its use也提供了一些额外的信息。
有关 enum
的一些解释,请参见 What is the purpose of Enum。
我的代码中有以下字段:
private static final int NUM_NANOSECONDS_IN_MILLISECOND = 1000000;
有人告诉我,为了类型安全,我应该为此使用枚举。这不是我熟悉的东西。但如果是这种情况,我不知道什么时候才适合在字段上使用 final 关键字。
什么时候应该使用 final 关键字而不是枚举?
使用枚举可以避免使用 int
,而不是 final
。使用专用枚举提供类型安全,因此您可以拥有更清晰的方法签名并避免错误。 final
用于防止在设置后更改值,并且无论变量的类型如何,这通常都是一种好的做法。
但是在这种情况下,我不确定枚举能给您带来什么价值。 NUM_NANOSECONDS_IN_MILLISECOND
似乎不应该是专用类型,正如@BoristheSpider 所建议的那样,您根本不需要这个字段。也许您的同事建议为单位使用枚举(例如 NANOSECOND
、MILLISECOND
等)而不是像这样存储比率。在那种情况下,现有的 TimeUnit
枚举绝对是你的朋友。
常量就是有名称的常量。 枚举是具有值的文字常量。我解释...
考虑:
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
很难做到这一点。或者至少,它变得非常不可读。
综上所述,对于您正在处理的特定情况,如果只有一个数字常量值,我会保持最终静态。如果只有一个值,就没有必要使用枚举。
我想说的是枚举的一般用例是当你有一个小的有限值集,这些值形成了你正在建模的某个集合并且你将枚举每个值。它们还可以帮助确保应包含这些值之一的字段不包含其他值。
在这种情况下,两者似乎都不适用。您也可以使用 NUM_NANOSECONDS_IN_MICROSECOND
、NUM_NANOSECONDS_IN_SECOND
、NUM_NANOSECONDS_IN_PI_MILLISECONDS
等,您不会一一列举。此外,您将要存储这些值的变量似乎不应该限于定义的常量的值。
老实说,这取决于您的需要。 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
做到这一点。由于这个问题,我什至在这里围绕一堆 public static final
属性写了一个 enum
包装器:
更重要的是,您无需深入源代码就可以轻松阅读什么值代表什么:
RGBColors red = RGBColors.RED;
现在让我们用 int 看看这个:
int red = RGBColors.RED;
我只能说
int red = 0; //red color
谁来告诉我后来的事呢?谁知道呢!
Anyways,简短的回答是,enums 在指定 enumerations[=59= 时非常有用],又名多个元素(或者您正在创建枚举单例),并且这些元素需要具有额外的方法或属性。
public enum MySingleton { //this is an enum singleton
INSTANCE;
public void doThings() {
System.out.println("hello!");
}
}
MySingleton.INSTANCE.doThings(); //hello!
常量 (public static final
) 在您使用它们时非常有用:常量.
在编写源代码时,最好尽可能依靠编译器来帮助您发现逻辑错误。一种方法是使用变量和常量类型,这样如果您对方法使用了错误的常量,编译器会将其标记为错误。
建议并不是关于使用 final
与 enum
,因为它们实际上是两个不同的编程概念。它使用 enum
来创建一个显式和唯一的类型,而不是使用 int
来创建一个显式和唯一性低得多的类型。如果您将 int
用作本应花费纳秒的函数的方法签名的一部分,那么编译器将接受任何 int
值。如果您改为使用 enum
,则仅允许 enum
中指定的那些值。使用其他任何东西都会导致编译器发出错误。
final
关键字是一种确保变量不能被覆盖或修改的方法,这样变量就像常量一样。 wikipedia article on final.
enum
中指定的值是常量,因此您可以选择使用现有的常量,或使用 enum
,常量,但是使用 enum
将提供来自编译器的安全检查,以便只有 enum
的指定值可以用于纳秒级的方法调用或变量赋值。
这里有一个explanation of final
with additional links from that stack overflow. Java method keyword final and its use也提供了一些额外的信息。
有关 enum
的一些解释,请参见 What is the purpose of Enum。