Java 1.5 introduced some new concepts at the Java language level. One of them is Generics, which you can make use mainly when creating type safe collections. This new concept facilitates the programmers’ life: being type safe, errors when working with collections can be caught at compile time (if you have a List<String>in hand, only Strings can be added to this list, neither Integers, Cats or Dogs ) and the programmer doesn’t have to cast when taking out an object of a collection. I was thus wondering whether there is any difference between List<?> and List<Object>. Let’s take a look at the following lines of Java code:

   1:import java.util.ArrayList;
   2:import java.util.List;
   3:
   4:public class Music
   5:{
   6:    abstract class Instrument
   7:    {
   8:    }
   9:
  10:    class Guitar
  11:            extends Instrument
  12:    {
  13:    }
  14:
  15:    class Flute
  16:            extends Instrument
  17:    {
  18:    }
  19:
  20:    class Drums
  21:            extends Instrument
  22:    {
  23:    }
  24:
  25:    public static void main(String [ ] args)
  26:    {
  27:        List<Instrument> instruments =
  28:            new ArrayList<Instrument>();
  29:        List<Guitar> guitars = new ArrayList<Guitar>();
  30:        List<Flute> flutes = new ArrayList<Flute>();
  31:        List<Drums> drums = new ArrayList<Drums>();
  32:        List<Integer> integers = new ArrayList<Integer>();
  33:        List<Object> objects = new ArrayList<Object>();
  34:        check(instruments);
  35:        check(guitars);
  36:        check(flutes);
  37:        check(drums);
  38:        check(integers);
  39:        validate(objects);
  40:        validate(drums);
  41:    }
  42:
  43:    private static void check(List<?> instruments)
  44:    {
  45:    }
  46:
  47:    private static void validate
  48:        (List<Object> instruments)
  49:    {
  50:    }
  51:}

If you try to execute the lines of code, you´ll note:

  • List<?>, which is the wildcard <?> bounded type, also know as List<capture-of ?>, simply means “any type.” That is, it could be a List of <Guitar>, <Flute>,<Drums>, whatever. It also means that you cannot ADD anything to the list referred to as List<?>.
  • List<Object> only accepts Object as an argument. Not Guitars, Drums, Flutes or Integers. If you have a method which the argument specifies List<Object>, this method can only take a List<Object>. The compiler allows you to add to the List<Object>, since you pass an Object as an argument.

So, there are differences between List<?> and List<Object>. The above code doesn´t compile, because an List<Drums> is being passed to a method which has a List<Object> as argument. But if you modify the method to this one:

   1:private static void validate
   2:        (List<? extends Object> instruments)
   3:{
   4:}

The code now compiles!! So, we saw the behavior of List<?> and List<? extends Object> is the same! They both means “I can refer to any type of object”. But neither List<?> nor List<?> nor List<? extends Object> are the same as List<Object>. When you see code using the wildcard notation (?), you can think: “this code refer to many options”. If you try to add something to a List<?>, the compiler won’t let you, because whether it were possible, it would be an unsafe operation, as you could pass a List<Guitar> to a method which receives a List<?> and add, say, a String to the list, as List<?> accepts “any type”. So now you may think: “Ok, Generics is a good feature, I can now create type safe collections and work with them in a safer way at compile time, that’s very good”. But everything isn’t the way we’d want it to be. If you try to mix Java generics code and legacy code,

   1:private static void add(List instruments)
   2:{
   3:    instruments.add("45");
   4:}

and

   1:add(instruments);
   2:add(guitars);
   3:add(flutes);
   4:add(drums);
   5:add(integers);
   6:add(objects);

It compiles!! But let’s deal with it in another post.