当前位置: 动力学知识库 > 问答 > 编程问答 >

java - 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>{

@Override

List<NullPointerException> foo(){

return new ArrayList<NullPointerException>();

}

}

GenericTest(Super<? extends Exception> s){

List<? extends Exception> list = s.foo();

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 set:

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 convertException:

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

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

Thanks for your help in advance!

网友答案:

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 = s.foo().get(0);
    }

This will compile fine

UPDATE

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 = s.foo();
        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>();

        addCats(dogs);
    }

    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 = s.foo();
        list.set(0, convertException(list.get(0)));
    }

and then make instanceof checks on your list elements.

Hope this helps

UPDATE 2

Why does convertException not know, that it will return the same type as the list has?

The problem is not that the compiler doesn't know that "F extends Exception == ? extends Exception". This piece of code:

GenericTest(Super<Exception> s){
        List<? extends Exception> list = getList();

    }

    <F extends Exception> List<F> getList(){...}

will compile. The problem is that you're using the set method on collections with wildcard, wich is forbidden, no matter what object are you actually passing.

网友答案:

You can use casting. Object is a superclass https://docs.oracle.com/javase/tutorial/java/IandI/objectclass.html

    Exception e =  (Exception) s.foo().get(0);

I think this is what you were aiming for?

    List<NullPointerException> ds = new GenericTest.Sub1().foo();
    Exception e2 = ds.get(0);
分享给朋友:
您可能感兴趣的文章:
随机阅读: