2014-02-05 4 views
5

Очень часто требуется быстрый набор значений, чтобы иметь возможность перебирать его. Вместо ручного создания экземпляра, добавления элементов или выполнения известной инициализации конструктора, которая создает набор из списка из массива (Set<String> mySet = new HashSet<String>(Arrays.AsList("a", "b", "c"))), я хотел создать функцию, которая должна выполнять эту работу для меня.Алмазный оператор; initialize paremeterized generic class

Помимо того, что я хочу, чтобы обеспечить общий параметр <S> использовать для сбора класса, я также хочу, чтобы обеспечить общий параметр <T> - фактический тип Collection.

Итак, мой первый подход был следующим:

public static <T extends Collection<S>, S> T initializeCollection(Class<T> concreteClass, S... objects) { 
    T result; 

    try { 
     result = concreteClass.newInstance(); 
     for (S s : objects) { 
      result.add(s); 
     } 

     return result; 
    } catch (InstantiationException e) { 
     return null; 
    } catch (IllegalAccessException e) { 
     return null; 
    } 
} 

Это работает довольно хорошо, и может быть использован как:

LinkedList<String> myList = StaticHelper.initializeCollection(LinkedList.class, "a", "b"); 

или

HashSet<Integer> mySet = StaticHelper.initializeCollection(HashSet.class, 1,2,3,4,5); 

от того, что я испытал на теперь это работает так, как ожидалось. Единственная проблема заключается в том, что валидатор заявляет, что происходит преобразование несохраненного типа. Используя пример Комплекса валидатор говорит

Type safety: The expression of type HashSet needs unchecked conversion to conform to HashSet<Integer> 

Когда я смотрю ближе возвращаемые значения интегрированной среды с указанием для моей функции выглядит следующим образом:

<HashSet, Integer> HashSet my.namespace.helper.CollectionHelper.initializeCollection(Class<HashSet> concreteClass, Integer... objects) 

Поэтому валидатор OFC считает, что он должен сделать несохраненный литой от HashSet до .

Но, на мой взгляд, возвращаемое значение функции равно T, что в значительной степени определяется как Collection<S> - и не как Collection.

Теперь я задаюсь вопросом, если:

  • Существует проблема с моей функции, и действительно unsave напечатанный происходит
  • Существует проблема с IDE, не показывая правильный ReturnValue и поэтому валидатор не смог выполнить эту работу должным образом.

Sidenode: Даже если хорошая альтернатива была размещена (который я уже использую) я очень заинтересован в решении этой проблемы.

public static <T extends Collection<S>, S> T<S> initializeCollection ... 

или с помощью

... initializeCollection(HashSet<Integer>.class,... 

, очевидно, недействительна синтаксис, но в основном будет выглядеть Что требуется.

+0

Я думаю, что проблема в том, что нет никакого способа для компилятора, чтобы получить общая информация из литерала '.class'. Поэтому я не думаю, что это можно сделать без предупреждения. – Keppil

ответ

3

Не очень прямой ответ, но вы могли бы сделать его проще с:

@SafeVarargs 
public static <T extends Collection<S>, S> T initializeCollection(T collection, S... objects) { 
    Collections.addAll(collection, objects); 
    return collection; 
} 

И назвать его:

HashSet<Integer> mySet = initializeCollection(new HashSet<>(), 1, 2, 3, 4, 5); 
+0

Thats довольно приятно также. Также валидатору нравится такой подход. :) – dognose

+0

никаких предупреждений (с аннотацией SafeVarargs). Я думаю, ваша проблема в том, что 'result = concreteClass.newInstance();' возвращает необработанный тип, поэтому я не думаю, что вы можете легко избавиться от предупреждения ... – assylias

+0

lso без этой аннотации У меня нет предупреждений. – dognose