简体   繁体   中英

How can I avoid an "Unchecked overriding" warning when interface method's generic return is implemented with a concrete type in Java?

This is an educational question that relates to a hobby project. Project Spring Boot MVC/REST app.

I would like to retain the flexibility to be able to create multiple implementations of Service and have list return a list of objects, depending on what the implementation requires.

I appreciate I could create some inheritance/implementation hierarchy to define the kinds of objects of which T could encompass. My problem with both of those answers is that some use cases for Service involve me needing to return Lists of Java Standard Lib types - types I would rather not inherit/extend/implement for my own custom classes, which I would prefer be kept as lean as possible.

import java.util.List;

interface Service {
    <T> List<T> list(String location, MyEnums.mediaType type );
}

class MyEnums {
    enum mediaType {
        IMAGE, VIDEO, AUDIO
    }
}

class LocalService implements Service {
    public List<MyConcreteClass> list(String location, MyEnums.mediaType type ) {
        List<MyConcreteClass> list = null;
        list.add(new MyConcreteClass(1, "foo", new byte[0]));
        return list;
    }
}

class MyConcreteClass implements Comparable<MyConcreteClass> {

    private final long id;
    private final String name;
    private final byte[] data;

    public MyConcreteClass(long id, String name, byte[] data) {
        this.id = id;
        this.name = name;
        this.data = data;
    }


    @Override
    public int compareTo(MyConcreteClass o) {
        return this.name.compareTo(o.name);
    }

    // Other methods omitted for brevity
}


The above code is only a simplified example of the actual app code - which compiles and runs without any (known) runtime bugs. However I get the compiler warning:

Unchecked overriding: return type requires unchecked conversion.

The presence of a warning makes sense to me - code consuming the Service interface/API could break at runtime if the return type requirement in the calling code is incompatible with the implementation, whereas the error would be caught at compile if I had a more specific List<> defined in the interface.

This would, of course, not be an issue if I had to wire in a concrete implementation into the code consuming my service - however the joys of Spring!

What am I doing wrong? How can I fix this? Are generics the right way to achieve a polymorphic list() function in my case?

You can eliminate the unchecked cast by declaring the interface itself with a type parameter (instead of the method). Like this:

interface Service<T> {
    List<T> list(String location, String type );
}

class LocalService implements Service<MyConcreteClass> {
    @Override
    public List<MyConcreteClass> list(String location, String type ) {
        // Some logic to retrieve, alter and return a list
        return null;
    }
}

class StringService implements Service<String> {
    @Override
    public List<String> list(String location, String type) {
        // TODO Auto-generated method stub
        return null;
    }
}

class MyConcreteClass {
    /// ...
}

(I changed a couple of things to make it compile, not relevant to the answer).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM