5

I have a two part question

My book states this "If the wildcard is specified without an upper bound, then only the methods of type Object can be invoked on the values of the wildcard type"

I have no idea what this could mean. What does this mean?

Also what are the limitations place on wild card types (unbounded and bounded)? For instance if I have a reference to MyClass<?> or MyClass<? extends SomeOtherClass>, what methods am I not allowed to call through that reference. I don't understand what the wild card allows or disallows me to do, which is probably why I don't understand the quote from the book.

I have an example for the second part:

class SomeOtherClass
{
[...]
}

class MyClass<T>
{
[...]
}

class Test
{
     public static void main(String[] arg)
     {
         MyClass<? extends SomeOtherClass> myClass = new MyClass<String>() // for instance what does the wild card reference limit me to in any way. In a general sence.
     }
}
Michael Currie
  • 13,721
  • 9
  • 42
  • 58
rubixibuc
  • 7,111
  • 18
  • 59
  • 98

3 Answers3

10

Wildcards bounds (upper and lower) are often mandatory for collections and classes returning objects of parameterized type.

You'll often hear about PECS, which means "Producer extends, Consumer super". I suggest you to read the answer to this question, to avoid duplicating answers.

  • To be more precise, when you define your wildcard with <? extends TheClass>, then you're telling the compiler that the wildcarded object is at least of type TheClass. Therefore, you are able to use this object like an instance of TheClass, and call any method this type proposes.

  • Now, when you define your wildcard as <? super TheClass>, you're telling the compiler that your wildcarded object type is implemented or extended by the TheClass type. It means that the object type may not be TheClass, but that a TheClass object can be used as an instance of your wildcarded reference. Therefore, you cannot call anything on that object, since its type is only known at runtime, but you can pass the object to methods waiting for a wildcarded object.

Examples:

private void foo(List<?> list) {
    Object o = list.get(0); // ok
    list.add(new Object()); // won't compile!

    // you cannot add anything, and only extract Object instances
}

private void foo(List<? extends TheClass> list) {
    Object o1 = list.get(0);   // ok
    TheClass o2 = list.get(0); // ok
    list.add(new Object());    // won't compile!
    list.add(new TheClass());  // won't compile!

    // You are sure that the objects are of a subtype of TheClass,
    // so you can extract TheClass instances safely. However, you cannot
    // add anything to this list since its type is not known (may be
    // different from TheClass, so the compiler does not allow anything).
}

private void foo(List<? super TheClass> list) {
    Object o1 = list.get(0);   // ok
    TheClass o2 = list.get(0); // won't compile!
    list.add(new Object());    // won't compile!
    list.add(new TheClass());  // ok

    // You are sure that the objects are of a type implemented by TheClass,
    // so you can add any TheClass instances to the list. However, you cannot
    // extract TheClass objects since the objects type may be just implemented
    // by TheClass, but different.
}
Community
  • 1
  • 1
Aurelien Ribon
  • 7,548
  • 3
  • 43
  • 54
  • I don't understand what the statement in my book means, can you explain it in the same context – rubixibuc Mar 20 '12 at 08:12
  • In the sentence, what do "methods of type Object mean"? That's where I am confused. Does it mean methods of the Object class? – rubixibuc Mar 20 '12 at 08:21
  • The statement means that if there is no upper bound for wildcard, then upperbound is Object class (the ancestor for every class in Java). And compiler may only garantee that methods of upper bound (here Object) will be present in the class wich specified by this generic. – yggdraa Mar 20 '12 at 08:24
  • For me, "a method of type XXX which can be invoked on a value" is a strange way to mean "a method taking a XXX instance as parameter", or "a method invoked with XXX value as parameter". – Aurelien Ribon Mar 20 '12 at 08:26
  • After you explained it seems that sentence doesn't really mean anything, because for an unbounded wildcard you can only return stuff anyway – rubixibuc Mar 20 '12 at 08:29
0

Normal generic;

ArrayList<Man> list= new ArrayList<Man>();
list.put(man); 
Man m = list.get(0);

Using wildcard with upper bound:

ArrayList<? extends Person> list= new ArrayList<? extends Person>();
list.put(man); //Man is a person..
Person p = list.get(0);

Using wildcard:

ArrayList<?> list= new ArrayList<?>();
list.put(man);
Object o = list.get(0);

If you use the wildcard you cannot know the generic type of ArrayList, hence you can only get Object out of the list which means that you are back to using ArrayLists the old way without generics..

barsju
  • 4,408
  • 1
  • 19
  • 24
  • That what I thought that everything is assumed to be the bound specified, but when I tested it I was able to extract not just Objects but whatever the upper bound was (of the generic not the referene). of let's say the generic class after type erasure. So if I use MyClass> and MyClass header equals MyClass will my variable of MyClass> be able to return SomeOtherClass if that makes sense and only that class. So would it be in that case that I can extract more than just objects of class Object – rubixibuc Mar 20 '12 at 08:00
  • 1
    No, your second example won't compile, since your list type may be `Woman`, which extends `Person` but is not related to `Man`. As the compiler can't know, it won't compile on line 2 (when using the .put() method). – Aurelien Ribon Mar 20 '12 at 08:04
  • The solution is to use `super` instead of `extends` in this second example. Therefore, the list type can be any type implemented by `Person`, so a `Man` object will fit it, and the compiler will accept it. That's the `PECS` paradigm: when you want to consume objects (ie. adding them to a list), you need `super`, not `extends` ;) – Aurelien Ribon Mar 20 '12 at 08:06
  • The example was very contrived, but if the upper bound for a generic is a specific class, then when you use unbounded wildcard can you only extract objects of that upper bound, or only Object no matter what – rubixibuc Mar 20 '12 at 08:07
  • If you don't bound the list, you can only extract Objects. However, note that if you set a lower bound (using `super`), you can also only extract Objects. There are many tutorials and manuals about generics bounds, look for them, that's very instructive :) – Aurelien Ribon Mar 20 '12 at 08:13
  • What if ArrayList was declared as class ArrayList instead of . Could I then only extract strings with unbounded wild card? – rubixibuc Mar 20 '12 at 08:16
0

For example you have <? extends MyClass> wildcard. This means that any class matching this wildcard may be of MyClass type or any of it's descendants. But since the only thing we know it is descendant of MyClass, we can only garantee that methods available on class MyClass are available to invoke.

For wildcard with bo upper bound <?> the upper bound will be Object class. And this means that all we know is that the class extends Object, so only methods that are garanteed to be present in this class are those that defined in Object class.

yggdraa
  • 2,002
  • 20
  • 23