假设您正在维护一个多年前发布的 API(在 java 获得 enum
支持之前),它定义了一个具有枚举值作为 int 的类:
public class VitaminType {
public static final int RETINOL = 0;
public static final int THIAMIN = 1;
public static final int RIBOFLAVIN = 2;
}
多年来,API 不断发展并获得了 Java 5 特有的功能(通用接口(interface)等)。现在您要添加一个新的枚举:
public enum NutrientType {
AMINO_ACID, SATURATED_FAT, UNSATURATED_FAT, CARBOHYDRATE;
}
“旧式”int-enum 模式没有类型安全性,不可能添加行为或数据等,但它已发布并正在使用。我担心混合使用两种样式的枚举对于 API 的用户来说是不一致的。
我看到三种可能的方法:
放弃并将新枚举(在我的虚构示例中为
NutrientType
)定义为一系列整数,例如VitaminType
类。您获得了一致性,但没有利用类型安全和其他现代功能。决定忍受已发布 API 中的不一致:保持
VitaminType
不变,并将NutrientType
添加为enum
.采用VitaminType
的方法仍被声明为采用 int,采用NutrientType
的方法被声明为采用 int。弃用
VitaminType
类并引入新的VitaminType2
枚举。将新的NutrientType
定义为枚举。
恭喜,在接下来的 2-3 年里,直到你可以杀死弃用的类型,你将处理每一个将VitaminType
作为 int 并添加的方法的弃用版本每个的新foo(VitaminType2 v)
版本。您还需要为每个已弃用的foo(int v)
方法及其相应的foo(VitaminType2 v)
方法编写测试,这样您的 QA 工作就会成倍增加。
什么是最好的方法?
最佳答案
API 消费者将 VitaminType 与 NutrientType 混淆的可能性有多大?如果不太可能,那么最好保持 API 设计的一致性,尤其是当用户群已经建立并且您希望最大限度地减少客户所需的工作/学习增量时。如果可能造成混淆,那么 NutrientType 可能应该变成一个枚举。
这不一定是一夜之间的大规模改变;例如,您可以通过枚举公开旧的 int 值:
public enum Vitamin {
RETINOL(0), THIAMIN(1), RIBOFLAVIN(2);
private final int intValue;
Vitamin(int n) {
intValue = n;
}
public int getVitaminType() {
return intValue;
}
public static Vitamin asVitamin(int intValue) {
for (Vitamin vitamin : Vitamin.values()) {
if (intValue == vitamin.getVitaminType()) {
return vitamin;
}
}
throw new IllegalArgumentException();
}
}
/** Use foo.Vitamin instead */
@Deprecated
public class VitaminType {
public static final int RETINOL = Vitamin.RETINOL.getVitaminType();
public static final int THIAMIN = Vitamin.THIAMIN.getVitaminType();
public static final int RIBOFLAVIN = Vitamin.RIBOFLAVIN.getVitaminType();
}
这允许您更新 API,并让您可以控制何时弃用旧类型并在内部依赖旧类型的任何代码中安排切换。
需要注意使字面值与那些可能已与旧消费者代码内联的值保持同步。
关于java - 随着 API 的发展,处理 "int enum"模式与 Java 枚举共存的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/341005/