0

Following is an example of Generics with wild card

public static void printListItems(List<object> list) {
        for (Object listItem : list)
            System.out.println(listItem);
    }

In this example we want to print list items of any type but it can’t print List<Integer>, List<String> etc. because they are not subtypes of List<Object>. This problem can be solved using unbounded wildcard.

public static void printListItems(List<?> list) {
    for (Object listItem : list)
        System.out.println(listItem);
}

I read this above code in Java tutorial. For the first example , it says it cannot work because List<String> is not sublass of List<Object>.

Then why it is so that in the second example the for loop is working with taking listItem as dataType of Object and iterating through List<String> elements.

4castle
  • 28,713
  • 8
  • 60
  • 94
SukhwaniP
  • 1
  • 1
  • 3
    I believe it's clearly explained: https://docs.oracle.com/javase/tutorial/java/generics/unboundedWildcards.html – PM 77-1 Dec 03 '16 at 04:08
  • 1
    You might also want to read "[Difference between super T> and extends T> in Java](http://stackoverflow.com/q/4343202/5221149)", keeping in mind that `?` implicitly means `? extends Object`, or as the [JLS](https://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.5.1) says it: *The wildcard `? extends Object` is equivalent to the unbounded wildcard `?`*. – Andreas Dec 03 '16 at 04:20
  • Because every element (String, Integer, whatever) is an Object. – Bohemian Dec 03 '16 at 06:22

3 Answers3

0

You are running into a false contradiction because you are equating the relationship between List<String> and List<Object> to the relationship between String and Object.

In the first example, the compiler will yell at you if you attempt to call printListItems with a List<String>, because List<String> does not extend List<Object>.

In other words: A list of strings cannot be treated as a list of objects, because (according to the type system) a list of strings is not a list of objects.

In the second example, the compiler will not yell at you, because you are treating the elements of the List, which are Strings, as Objects. Unlike the case with the lists, String does extend Object.

In other words: A string can be treated as an object, because (according to the type system) a string is an object.

Dan
  • 682
  • 5
  • 17
0

when the type-declaration of generic class contain wildcard character, its subclass type can be extend in two dimension.


E.g. Collection<?extends Number>

  • its subclass type can be extend in dimension Collection, for List and Set are all subclass type of Collection so List<? extends Number> and Set<? extends Number>are all subclass type of Collection<? extends Number>
  • its subclass type can be extend in dimension Number, because Integer 、Double are all subclass type of Number so Collection<Double> and Collection<Integer> are all subclass of Collection<? extends Number>

about your second, as Andreas explained in comment, List is equal to List<? extend Object> and based on the second dimension extend List<String> is **subclass** of List<?>

nail fei
  • 1,887
  • 1
  • 12
  • 29
0

What you've done is not generic. This is a generic function

public static <T> void printListItems(List<T> list) {
    for (T listItem : list) {
        System.out.println(listItem);
    }
}

Example:

import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;

public class Main {
    public static <T> void printListItems(List<T> list) {
        for (T listItem : list) {
            System.out.println(listItem);
        }
    }

    // arguments are passed using the text field below this editor
    public static void main(String[] args) {
        List<Integer> l = new ArrayList<>(Arrays.asList(1,2,3,4,5));
        List<String> s = new ArrayList<>(Arrays.asList("Hello", "World"));
        printListItems(l);
        printListItems(s);
    }
}

Output

1
2
3
4
5
Hello
World
smac89
  • 26,360
  • 11
  • 91
  • 124