In Java, is it possible to specify a generic method that matches lists containing any objects except enums?
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?
}
}
- I'm under the impression that Java generics does not support <T does not extend Something>-style syntax, but I'd like to be know for sure - and preferably be proven wrong :).
- If I can't implement this limitation with generics, what is the best possible workaround? My current plan is below; is a better implementation possible?
public static <T> void bar(List<T> argument, Class<T> argumentType) { if (Enum.class.isAssignableFrom(argumentType)) { throw new IllegalArgumentException("Enums are disallowed."); } }
Edit: I'm interested in this because I have an API that allows the consumer to:
- Pass in a List of T and specify whether to return references to the T's in the list or clones of the T's:
public <T> void setList(List<T> contents, boolean returnClones)
- Retrieve the T's from the list:
public <T> T get(int index)
Of course, if T is an Enum, then specifying returnClones with true doesn't make sense - we can't create a clone of the Enum. There are also other cases where cloning doesn't work (e.g. a no-args constructor is not available). I'm trying to make the API as robust as possible.
Edit #2: I know Enums are immutable; I'm looking for the best way of preventing the caller from accidentally specifying invalid arguments to the API. The caller should never
- Pass in a List<SomeEnumType> and specifying that clones should be returned. This doesn't make sense.
- Pass in a List<SomeObjectWithoutNoArgsConstructor> and specifying that clones should be returned. This makes sense but is something we cannot support (it might be possible to clone the objects, but without a no-args constructor we don't know how).
Cloneable is a good suggestion, but the purpose of the interface is different: "A class implements the Cloneable interface to indicate to the Object.clone() method that it is legal for that method to make a field-for-field copy of instances of that class." (Cloneable JavaDoc). Since we're using Dozer for our cloning instead of calling clone() on the source object, I think Cloneable would unfortunately end up hurting more than helping in this case.
Cloneable