【发布时间】:2014-02-10 07:49:27
【问题描述】:
在Java中,是否可以指定一个通用方法来匹配包含任何对象除了枚举的列表?
public class Foo {
public enum MyEnum {
ENUM_VALUE
}
public static <T ...generics magic...> void bar(List<T> argument) {
// .. code
}
public static void test() {
Foo.bar(Arrays.asList(new Object())); // OK
Foo.bar(Arrays.asList(new Exception())); // Still OK
Foo.bar(Arrays.asList(MyEnum.ENUM_VALUE)); // Compiler error, please?
}
}
- 我的印象是 Java 泛型不支持
样式的语法,但我想确定一下 - 最好证明是错误的 :)。 - 如果我不能用泛型实现这个限制,最好的解决方法是什么?我目前的计划如下;是否有更好的实现方式?
public static <T> void bar(List<T> argument, Class<T> argumentType) { if (Enum.class.isAssignableFrom(argumentType)) { throw new IllegalArgumentException("Enums are disallowed."); } }
编辑:我对此很感兴趣,因为我有一个 API 允许消费者:
- 传入 T 的列表并指定是返回对列表中 T 的引用还是 T 的克隆:
public
void setList(List contents, boolean returnClones)
- 从列表中检索 T:
public
T get(int index)
当然,如果 T 是 Enum,那么将 returnClones 指定为 true 是没有意义的 - 我们无法创建 Enum 的克隆。还有其他情况下克隆不起作用(例如,无参数构造函数不可用)。我正在努力使 API 尽可能健壮。
编辑#2:我知道枚举是不可变的;我正在寻找防止调用者意外向 API 指定无效参数的最佳方法。调用者永远不应该
- 传入 List
并指定应返回的克隆。这没有意义。 - 传入 List
并指定应返回的克隆。这是有道理的,但我们无法支持(可能可以克隆对象,但如果没有无参数构造函数,我们不知道如何)。
Cloneable 是一个很好的建议,但接口的目的不同:“一个类实现了 Cloneable 接口以向 Object.clone() 方法表明该方法创建字段是合法的-该类实例的字段副本。" (Cloneable JavaDoc)。由于我们使用 Dozer 进行克隆,而不是在源对象上调用 clone(),我认为在这种情况下,Cloneable 最终会带来更多伤害而不是帮助。
【问题讨论】:
-
您的解决方法似乎是合理的。你为什么要这样做?
-
你可以强制你的论点实现
Cloneable -
为什么需要克隆?通常,克隆用于返回一个新对象,以防止用户修改原始对象。由于 Enum 像 int,long,String 一样不可修改,所以它仍然符合目的。在这里允许枚举似乎没问题。只是我的观点。也许您还有其他顾虑。