Markus H Markus H - 1 year ago 75
Java Question

Why does my generic function return different captures as it gets?

I have a superclass with a generic type extending a supertype (

<E extends ...>
). This class has an abstract method that returns a list of the generic type.

Also I have a few subclasses implementing the abstract method.

When I call this method and try to replace objects in the list, the java compiler shows an error. I think the error is because my converting function returns a different capture of the type as it gets as parameter.

Here is a sample code using Exception as generic supertype:

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

public class GenericTest {

abstract class Super<E extends Exception>{
abstract List<E> foo();

class Sub1 extends Super<NullPointerException>{
List<NullPointerException> foo(){
return new ArrayList<NullPointerException>();

GenericTest(Super<? extends Exception> s){
List<? extends Exception> list =;
list.set(0, convertException(list.get(0)));

static <F extends Exception> F convertException(F exception){...}

There are two error occurs in the line

list.set(0, convertException(list.get(0)));

The compiler says for

The method set(int, capture#2-of ? extends Exception) in the type List<capture#2-of ? extends Exception> is not applicable for the arguments (int, capture#3-of ? extends Exception)

and for

Type mismatch: cannot convert from capture#3-of ? extends Exception to capture#2-of ? extends Exception

Why doesn't convertEException return the same
as it gets? It takes F and returns F.

Thanks for your help in advance!

Answer Source

This is because you are passing Super to the constructor as a raw type. You are not using the generic. Since you don't specify the generic type, the compiler considers the list as a list of Object.

It should be like this:

GenericTest(Super<Exception> s){
        Exception e =;

This will compile fine


The compiler says for set

The method set(int, capture#2-of ? extends Exception) in the type List is not applicable for the arguments (int, capture#3-of ? extends Exception)

Java doesn't allow you to add or update elements of a Collection when you're using wildcard. So, using:

List<? extends Exception> list =;
        list.set(0, /*anything but null*/);

is forbidden. The reason is to avoid this situation:

class Animal {}
class Dog extends Animal {}
class Cat extends Animal {}

public void method() {

        List<Dog> dogs = new ArrayList<Dog>();


    void addCats(List<? extends Animal> list) {
        list.add(new Cat());

You see the point? If adding operation were allowed, you would risk to add cats in an list of dogs.

Back to your problem. I don't understand precisely what you have to do, if you really need a list with a specific subtype of exception, I suggest you to make also GenericTest as a generic class . Otherwise you can declare your list as a simple list of Exception:

GenericTest(Super<Exception> s){
        List<Exception> list =;
        list.set(0, convertException(list.get(0)));

and then make instanceof checks on your list elements.

Hope this helps

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download