1

I've been testing supertype generics with Java, but I've come to a roadblock. This is the sample code I was testing:

import java.util.*;

class GenericTests {
    public static void main( String[] args ) {      
        List<B> list3 = new ArrayList<B>();
        testMethod( list3 );
    }

    public static void testMethod( List<? super B> list ) {
        list.add( new A() );
        list.add( new B() );
    }
}

class A { }

class B extends A { }

When compiled, the error is:

GenericTests.java:20: error: no suitable method found for add(A)
            list.add( new A() );
                ^
method List.add(int,CAP#1) is not applicable
  (actual and formal argument lists differ in length)
method List.add(CAP#1) is not applicable
  (actual argument A cannot be converted to CAP#1 by method invocation conve
rsion)
where CAP#1 is a fresh type-variable:
CAP#1 extends Object super: B from capture of ? super B
1 error

I thought that given the lower bound of B, you could add any supertype? Or does this only apply to the references (i.e. arguments within the method signature) because allowing supertypes would break the type checking?

user2403871
  • 13
  • 2
  • 4
  • 1
    So you though any `A` (more generic) instance could be a `B` (more specific) instance? Are you really aware of the difference between super classes and sub classes to begin with? – Luiggi Mendoza May 21 '13 at 03:08
  • write private helper method for that add operation, check : http://docs.oracle.com/javase/tutorial/java/generics/capture.html – Martin V. May 21 '13 at 03:10
  • Yeah, that fact (sub as super, but not vice-versa) completely flew over my head when I was thinking about this. Now it seems much clearer. – user2403871 May 21 '13 at 04:00
  • related: [Java Generics: What is PECS?](http://stackoverflow.com/questions/2723397/java-generics-what-is-pecs). – Paul Bellora May 21 '13 at 04:00
  • possible duplicate of [java generics super keyword](http://stackoverflow.com/questions/3847162/java-generics-super-keyword) – Paul Bellora May 21 '13 at 04:10

2 Answers2

3

The declaration List<? super B> list says that list is a List of objects of some type that B inherits from. But this type need not be compatible with A. Suppose the hierarchy had been:

public class A {...}

public class C extends A {...}

public class B extends C {...}

Then, list could be a List<C>. But then list.add(new A()) is illegal. An instance of A is not an instance of C. The compiler only knows that instances of B or a subclass can be added to list.

Eric Jablow
  • 7,874
  • 2
  • 22
  • 29
  • Thanks, this entirely makes sense, not sure why I thought breaking type checking and inheritance was the answer. – user2403871 May 21 '13 at 03:39
  • 2
    +1 Though there's actually no need for `C` in the example. A `List super B>` might be a `List`, in which case adding a `new A()` shouldn't be allowed. – Paul Bellora May 21 '13 at 04:00
  • That's true. I just made the possibilities obvious. Yours is the minimal example. – Eric Jablow May 21 '13 at 04:13
0

You got the idea of ? super B differently than it actually is. What super do here is something like bellow:

public static void main( String[] args ) {      
    List<B> list3 = new ArrayList<B>();
    testMethod( list3 );

    List<A> listA = new ArrayList<>();
    testMethod(listA); --> U can pass a list of A
}

public static void testMethod( List<? super B> list ) {
    list.add( new B() );
}

This answer discuss the fact in detail.

Community
  • 1
  • 1
Mohayemin
  • 3,841
  • 4
  • 25
  • 54