Creating New Generic Object with Wildcard

Creating new generic object with wildcard

It's invalid syntax to instantiate a generic type with wildcards. The type List<? extends Number> means a List of some type that is or extends Number. To create an instance of this type doesn't make sense, because with instantiation you're creating something specific:

new ArrayList<? extends Number>();//compiler:"Wait, what am I creating exactly?" 

Generic types with wildcards only make sense for variables and method parameters, because this allows greater freedom in what can be assigned/passed into them.

//compiler:"Okay, so passing in a List<Integer> or a List<Double> are both fine"
public void eatSomeNumbers(List<? extends Number> numbers) {
for (Number number : numbers) {
System.out.println("om nom " + number + " nom");
}
}

Make sure to keep in mind the limitations that come with using wildcards.

List<? extends Number> numList = ...
numList.add(new Integer(3));//compiler:"Nope, cause that might be a List<Double>"

As for your first example, the diamond is a new feature in Java 7 that allows the compiler to infer the type of the new generic instance, based on the type of the variable it's assigned to. In this case:

List<? extends Number> x = new ArrayList<>();

The compiler is most likely inferring new ArrayList<Number>() here, but what's inferred hardly matters, as long as it's a valid assignment to the given variable. This was the reason for the diamond operator being introduced - that specifying the generic type of a new object was redundant, as long some generic type would make it a valid assignment/argument.

This reasoning only makes sense if you remember that generics in Java are a purely compile-time language feature, because of type erasure, and have no meaning at runtime. Wildcards exist only because of this limitation. By contrast, in C# generic type information sticks around at runtime - and generic wildcards don't exist in that language.

Java Generic Wildcard Constructor not accepting objects?

The issue here is that List<RandomizerEntry<ItemStack>> is not a subtype of List<RandomizerEntry<?>> so your constructor is not applicable to your argument. See this section of the Java tutorial which specifically addresses this misunderstanding.

As for the IDE suggestion to create another constructor, this won't work because in Java it is not possible to "overload a method where the formal parameter types of each overload erase to the same raw type" (details).

To solve the issue one way is simply to make the type of your local variable compatible with your constructor, although this will of course limit what you can do with it:

List<RandomizerEntry<?>> randomizerList = new ArrayList<>();

Java generics, Unbound wildcards ? vs Object

There are two separate issues here. A List<Object> can in fact take any object as you say. A List<Number> can take at least Number objects, or of course any subclasses, like Integer.

However a method like this:

public void print(List<Number> list);

will actually only take a List which is exactly List<Number>. It will not take any list which is declared List<Integer>.

So the difference is List<?> will take any List with whatever declaration, but List<Object> will only take something that was declared as List<Object>, nothing else.

The last quote simply states, that List<?> is a list for which you literally don't know what type its items are. Because of that, you can not add anything to it other than null.

How can elements be added to a wildcard generic collection?

Use this instead:

1  public List<? extends Foo> getFoos()
2 {
3 List<Foo> foos = new ArrayList<Foo>(); /* Or List<SubFoo> */
4 foos.add(new SubFoo());
5 return foos;
6 }

Once you declare foos as List<? extends Foo>, the compiler doesn't know that it's safe to add a SubFoo. What if an ArrayList<AltFoo> had been assigned to foos? That would be a valid assignment, but adding a SubFoo would pollute the collection.

Returning List of Generic Type Objects using Wildcards

You can cast the result which would make the compiler errors go away but you'd have an unsafe cast which seems like a code smell:

List<A> testAList = (List<A>) getGenericList(true);
List<B> testBList = (List<B>)getGenericList(false);

Also if the boolean input is not a strict requirement you can do something like this as well:

public <T extends Z> List<T> getGenericList(Class<T> klass) {
List<T> list = new ArrayList<T>();
try {
list.add(klass.newInstance());
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return list;
}

can we use wildcards at class level in java

You cannot.

From Wiki of WildCard

The wildcard ? in Java is a special actual parameter for the instantiation of generic (parameterized) types. It can be used for the instantiation, not in the definition of a generic unit.



Related Topics



Leave a reply



Submit