【问题标题】:Excluding enums from Java generic method parameters从 Java 泛型方法参数中排除枚举
【发布时间】: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?
    }
}
  1. 我的印象是 Java 泛型不支持 样式的语法,但我想确定一下 - 最好证明是错误的 :)。
  2. 如果我不能用泛型实现这个限制,最好的解决方法是什么?我目前的计划如下;是否有更好的实现方式?
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 一样不可修改,所以它仍然符合目的。在这里允许枚举似乎没问题。只是我的观点。也许您还有其他顾虑。

标签: java generics


【解决方案1】:

我做过一次重构,将一个长参数更改为一个对象。解决方案是执行以下操作:

/**
 * Not for enums.
 * @param x use not an enum.
 */
@Deprecated
public <E extends Enum<E>> void f(E x) {
    throw new IllegalArgumentException("...");
    // Or better throw new UnsupportedOperationException("...");
}

public <T> void f(T x) {
    ...
}

有了 IDE 支持,这会做得很好。


最好在 javadoc 和异常消息中提及改用什么,其他 f 左右。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多