从Java泛型方法参数中排除枚举

时间:2014-02-10 07:49:27

标签: java generics

在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泛型不支持&lt; T不扩展Something&gt; -style语法,但我想肯定地知道 - 并且最好被证明是错误的:)。
  2. 如果我无法使用泛型实现此限制,那么最佳解决方法是什么?我目前的计划如下;是否可以更好地实施?
  3. 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&lt; T&gt; void setList(List&lt; T&gt; contents,boolean returnClones)

    • 从列表中检索T:
      

    public&lt; T&gt; T get(int index)

    当然,如果T是Enum,那么使用true指定returnClones是没有意义的 - 我们无法创建Enum的克隆。还有其他一些克隆不起作用的情况(例如,没有args构造函数不可用)。我正在努力使API尽可能健壮。

    编辑#2:我知道枚举是不可变的;我正在寻找阻止调用者意外地为API指定无效参数的最佳方法。来电者永远不应该

    • 传入列表&lt; SomeEnumType&gt;并指定应返回克隆。这没有意义。
    • 传入List&lt; SomeObjectWithoutNoArgsConstructor&gt;并指定应返回克隆。这是有道理的,但是我们不能支持(可能有可能克隆对象,但没有no-args构造函数,我们不知道如何)。

    Cloneable是一个很好的建议,但是接口的目的是不同的:“一个类实现了Cloneable接口,以向Object.clone()方法表明该方法制作字段是合法的 - 该类实例的for-field副本。“(Cloneable JavaDoc)。由于我们使用Dozer进行克隆而不是在源对象上调用clone(),我认为Cloneable最终会在这种情况下造成伤害而不仅仅是帮助。

1 个答案:

答案 0 :(得分:1)

我做过一次重构,其中一个long参数更改为Object。解决方案是做类似的事情:

/**
 * 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左右。