92

What is the difference between these 2 functions?

static void gPrint(List<? extends Number> l) {
    for (Number n : l) {
        System.out.println(n);
    }
}

static <T extends Number> void gPrintA(List<T> l) {
    for (Number n : l) {
        System.out.println(n);
    }
}

I see the same output.

vikky.rk
  • 3,989
  • 5
  • 29
  • 32

4 Answers4

56

There is no difference in this case, because T is never used again.

The reason for declaring a T is so that you can refer to it again, thus binding two parameter types, or a return type together.

Thilo
  • 257,207
  • 101
  • 511
  • 656
  • Agreed! So is there a case where only '?' will do the job for me but not 'T'. Or whatever that can be done by wildcard can be done using 'T'? – vikky.rk Jul 16 '12 at 01:11
  • 15
    If there is only one `?`, then it is equivalent. If there is more than one `?`, then you have to use either `T` or `?`, depending on if you need the two types to be the same, or want to allow for them to be different. If you have a method `x( extends Number> a, extends Number> b)`, you can call it with an Integer and a Long. If you have `T a, T b`, they both need to be of the same type. – Thilo Jul 16 '12 at 01:13
  • 1
    But I can still do x(T a, U b). So which is the preferred way? Is it preferred to not use Wildcards (whenever possible)? – vikky.rk Jul 16 '12 at 01:24
  • 1
    It is just a matter of style. I'd prefer wildcards, to make it clear that the type is not bound to another type. – Thilo Jul 16 '12 at 01:26
49

The difference is you can't refer to T when using a wildcard.

You aren't right now, so there is "no difference", but here's how you could use T to make a difference:

static <T extends Number> T getElement(List<T> l) {
    for (T t : l) {
        if (some condition)
            return t;
    }
    return null;
}

This will return the same type as whatever is passed in. eg these will both compile:

Integer x = getElement(integerList);
Float y = getElement(floatList);
Bohemian
  • 412,405
  • 93
  • 575
  • 722
  • So when is wildcard really needed? – vikky.rk Jul 16 '12 at 01:25
  • 5
    The wildcard is not really "needed", but provides for less typing when indeed it is an unbound type (no need to give it a name). The resulting code is equivalent. This is similar to the difference between `int a = 1; return a` versus `return 1`. Or writing `` instead of `` – Thilo Jul 16 '12 at 01:27
  • @Bohemian Wait a second, how is that code correct? Isn't there type erasure that occurs at runtime, leading that code to fail out at runtime? – Dr. Java Nov 17 '20 at 21:19
  • 1
    @Dr.Java Yes and no. Yes there’s runtime type erasure, but there’s no error at runtime because at compile time the type was *inferred* and type safety was assured. See [Type Inference](https://docs.oracle.com/javase/tutorial/java/generics/genTypeInference.html) – Bohemian Nov 18 '20 at 10:09
15

T is a bounded type, i.e. whatever type you use, you have to stick to that particular type which extends Number, e.g. if you pass a Double type to a list, you cannot pass it a Short type as T is of type Double and the list is already bounded by that type. In contrast, if you use ? (wildcard), you can use "any" type that extends Number (add both Short and Double to that list).

ns89
  • 263
  • 1
  • 3
  • 10
-2

When you use T you can perform all type of actions on List. But when you use you can not perform add.

T - as same as object reference with full access
? - give partial access

static void gPrint(List<? extends Number> l) {
 l.add(1); //Will give error
for (Number n : l) {
    System.out.println(n);
}

static <T extends Number> void gPrintA(List<T> l) {
l.add((T)1); //We can add
for (Number n : l) {
    System.out.println(n);
}
Kanagaraj M
  • 956
  • 8
  • 18