2014-02-10 4 views
1

В Java можно указать общий метод, который соответствует спискам, содержащим любые объекты за исключением перечислений?Исключение перечислений из параметров общего метода 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 дженериков не поддерживает < T не расширяет что-то > -стиль синтаксиса, но я хотел бы быть знать наверняка - и желательно быть опровергнуто :) ,
  2. Если я не могу реализовать это ограничение с помощью дженериков, какое наилучшее возможное обходное решение? Мой текущий план ниже; возможно ли лучшее осуществление?
public static <T> void bar(List<T> argument, Class<T> argumentType) { 
    if (Enum.class.isAssignableFrom(argumentType)) { 
    throw new IllegalArgumentException("Enums are disallowed."); 
    } 
} 

Edit: Я заинтересован в этом, потому что у меня есть API, который позволяет потребителю:

  • перевале в Список T и указать, следует ли возвращать ссылки на Т в списке или клонах Т:

общественного <T> недействительный Setlist (Список <T> содержания, булевы returnClones)

  • Получить Т из списка:

общественного <T> T прибудет (INT индекса)

Конечно, если T - Enum, то указание returnClones с истинным не имеет смысла - мы не можем создать клон Enum. Существуют и другие случаи, когда клонирование не работает (например, конструктор no-args недоступен). Я пытаюсь сделать API максимально надежным.

Редактировать # 2: Я знаю, что перечисления неизменяемы; Я ищу лучший способ помешать вызывающему пользователю случайно указать неверные аргументы API. Вызывающий никогда не должен

  • Pass в список <SomeEnumType> и указав, что клоны должны быть возвращены. Это не имеет смысла.
  • Передать список <SomeObjectWithoutNoArgsConstructor> и указать, что клоны должны быть возвращены. Это имеет смысл, но мы не можем поддерживать (возможно, можно клонировать объекты, но без конструктора no-args мы не знаем, как).

Cloneable хорошее предложение, но цель интерфейса отличается: "класс реализует Cloneable интерфейс для указания метода Object.clone(), что он является законным для этого способ сделать поле -for-field копия экземпляров этого класса. "(Cloneable JavaDoc).Поскольку мы используем Dozer для нашего клонирования вместо вызова clone() на исходном объекте, я думаю, что Cloneable, к сожалению, в конечном итоге причинит больше вреда, чем помогает в этом случае.

+0

Ваша работа вокруг кажется разумной. Почему вы хотите это сделать? –

+0

Вы можете заставить свой аргумент реализовать 'Cloneable' – ooxi

+0

Зачем вам клонировать? Обычно клонирование используется для возврата нового объекта, чтобы пользователь не мог изменить исходный. Поскольку Enum немодифицируется, как int, long, String, он по-прежнему соответствует цели. Кажется, нормально разрешить перечисление здесь. Просто мое мнение. Может быть, у вас есть другая проблема. – Merlin

ответ

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 или около того.

Смежные вопросы