Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Diamond Operator; initialize paremeterized generic class

Very often one needs a quick collection of values to be able to iterate over it. Instead of manually creating the instance, adding items or doing the well known constructor-initialization that creates a set out of a list out of an array (Set<String> mySet = new HashSet<String>(Arrays.AsList("a", "b", "c"))) I wanted to create a function that should do the job for me.

Beside the Fact, that I want to provide the generic parameter <S> to use for the collection-class, i also want to provide the generic parameter <T> - the actual type of the Collection.

So, my first approach was the following:

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;
    }
}

This works quite well and could be used like:

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

or

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

from what I tested by now this works as expected. The only problem is that the validator states, that theres an unsave type conversion going on. Using the Example of the Set, the validator says

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

When I look closer at the return value the IDE is stating for my function it looks like this:

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

Therefore the validator ofc thinks, that he has to do a unsave cast from HashSet to HashSet<Integer>.

But in my opinion, the return value of the function is T, which is pretty much defined as Collection<S> - and not as Collection.

Now i'm wondering if:

  • There is an Issue with my function, and really an unsave typecast happening
  • There is an Issue with the IDE, not showing the correct returnValue and therefore the validater couldn't do it's job properly.

Sidenode: Even if a good alternative has been posted (which i am already using) i'm quite interested in the solution to this problem.

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

or using

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

is obviously invalid syntax, but basically would look like whats required.

like image 335
dognose Avatar asked Oct 20 '22 15:10

dognose


1 Answers

Not really a direct answer but you could make it simpler with:

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

And call it with:

HashSet<Integer> mySet = initializeCollection(new HashSet<>(), 1, 2, 3, 4, 5);
like image 79
assylias Avatar answered Oct 27 '22 10:10

assylias