6

So I have gone through official java tutorial,https://docs.oracle.com/javase/tutorial/java/generics/index.html , also searched through stackoverflow, and it turns out that there is not much difference between using <E> and <?>, one as I can understand is normal generic form and the other one is wildcard. So far the only difference I came across is that when using <E> or <E extetnds BlaBlaClass> we can refer to the type as E, while otherwise we don't know any information about the collection or array or the type at all.

My question is: is there any advantage of using <?> (wildcard) over normal generics <E>? and if so, what is the scenario of this situation? And why would someone use wildcards at all?

I have looked at Difference between generic type and wildcard type , Difference between ? (wildcard) and Type Parameter in Java , When to use generic methods and when to use wild-card? , Java Generics ? , E and T what is the difference? . So far it looks like <?> is poorer version of <E>

user6396911
  • 123
  • 1
  • 6
  • Read properly the questions you looked at. For example the second one explains that you can't insert an item to the list defined with the `?`.. – Gilad Green Jul 13 '17 at 16:30
  • 1
    @GiladGreen so that's exactly what I am asking, wildcards have no advantage over type parameters what so ever? – user6396911 Jul 13 '17 at 16:37
  • Its not about advantage but about what you want - If you don't need to know what type and not need to add (for example just call `toString` of all items in list - then `List>` is perfect – Gilad Green Jul 13 '17 at 16:38
  • @GiladGreen so this means that the question Im asking is similar to: whats the advantage of using natural numbers over decimals (i.e 1,2,3,4 and 1.0, 2.0 ...) as if I want to count the number of apples natural numbers are perfectly fine, say I don't need to count parts of apples? – user6396911 Jul 13 '17 at 16:47

2 Answers2

12

The unbounded wildcard ? is useful in cases where it doesn't matter what the generic type is. Let's say you have a method that checks a list's size and clears it if it's too large, and you want it to accept lists with any type of elements:

public static <E> void checkList(List<E> list, int max) {
    if (list.size() > max) list.clear();
}

You declare the type variable E, but the size() and clear() methods don't need it, so it goes unused. Instead, you can do this:

public static void checkList(List<?> list, int max) {
    if (list.size() > max) list.clear();
}

This simplifies the method declaration, and makes it clear to other programmers that this method isn't concerned with the type of the list elements.


Unbounded wildcards can also be used in field or local variable declarations (where type variables cannot be declared) to allow assignment of values with any generic type.

public static void main(String[] args) {
    List<?> list;
    list = new ArrayList<Object>();
    list = new ArrayList<String>();
    list = new ArrayList<Integer>();
}

If this was List<Object>, the last two lines would not compile. It could be <? extends Object>, but this is equivalent to <?>.

For a slightly more practical example, say you wanted a map where the values can be any list:

public class MyClass {
    public final Map<String, List<?>> lists = new HashMap<>();
}

Finally, if you ever need to cast a value to a generic class and you aren't certain of its type parameters, you must use ? for them. (Never use raw types, it disables generic type safety checks.) A good example of this is in the common equals() implementation:

@Override
public boolean equals(Object obj) {
    if (this == obj) return true;
    if (obj == null) return false;
    if (getClass() != obj.getClass()) return false;
    MyClass<?> other = (MyClass<?>) obj;
    if (!myField.equals(other.myField)) return false;
    return true;
}

For more info on Java generics, check out Angelika Langer's Generics FAQ.

Sean Van Gorder
  • 3,393
  • 26
  • 26
  • can we do all the same stuff with the i.e. with a type parameter? – user6396911 Jul 13 '17 at 17:35
  • Not sure what you're asking. In the `checkList` method, if you define the parameter as `List`, you won't be able to give it a `List` value anymore. You shouldn't narrow the types of parameters unnecessarily. The other examples require the use of `?`. – Sean Van Gorder Jul 13 '17 at 17:43
  • Whats the difference between using and >, i mean when should u use one or another? – user6396911 Jul 13 '17 at 17:49
  • I don't think I can explain it any clearer than I did in my answer. In the `checkList` example, the code functions the same with `` and `>`, but the latter is simpler and clearer. The other examples cannot use a type variable like `` because you can't declare a type variable in a field or local variable declaration, so there isn't even a choice between the two. – Sean Van Gorder Jul 13 '17 at 17:57
  • I added a link that should help explain things beyond this specific question. – Sean Van Gorder Jul 13 '17 at 18:22
3

Let's say you're working with instances of some class Foo.

  • If you have a Foo, you can add it to a List<Foo> or List<? super Foo> but not to a List<?> or List<? extends Foo>.
  • If you want a Foo, you can get it from a List<Foo> or List<? extends Foo> but not from a List<?> or List<? super Foo> (it'll come back typed as just Object)

So, that's the advantage: you get to interact with the list in terms of its Foo elements.

If all you care about is whether the List is empty, or something else that doesn't rely on the specific shape of its elements, then a List<?> is fine for that.

This applies just as well to a situation where you're in a generic method, and are working on instances of a generic E rather than a specific class Foo:

public <E> void addIfEmpty(E element) {
    List<? super E> listOfE = ...; // or List<E>
    if (!listOfE.isEmpty()) {
        listOfE.add(element);
    }

    List<?> listOfWild = ...;
    if (!listOfWild.isEmpty()) {
        listOfWild.add(element); // compilation error
    }
}
yshavit
  • 42,327
  • 7
  • 87
  • 124
  • Of course you can use List and List super Foo>, but what is the difference between List super Foo> and List? – user6396911 Jul 13 '17 at 16:40
  • 1
    Well, what's your `E` there? `List` doesn't mean anything (and won't compile), so I'm not sure exactly what you mean by it. I just updated my answer with an example that hopefully clears things up. If it doesn't, I think you may need to sit for a bit and really pin down what the specific scenarios you're thinking of are, and what will work or not work in each of them. – yshavit Jul 13 '17 at 16:43
  • Nicely explained. – Kanagavelu Sugumar Nov 09 '18 at 07:15