Java Generics: Overriding generic methods, wildcard shorthand?

蹲街弑〆低调 提交于 2020-02-03 09:32:18

问题


If I have an interface with a generic method like the following:

public interface Thing {
    void <T extends Comparable<? super T>> doSomething(List<T> objects);
}

I need that ugly generic typespec in some places, but most implementations don't actually need it:

public class ICareAboutSortingThing implements Thing {
    @Override
    public void <T extends Comparable<? super T>> doSomething(List<T> objects) { ... }
}

public class IDontCareAboutSortingThingx100 implements Thing {
    @Override
    public void <T extends Comparable<? super T>> doSomething(List<T> objects) { ... }
}

What I would want to write is something like:

public class IDontCareAboutSortingThingx100 implements Thing {
    @Override
    public void <?> doSomething(List<?> objects) { ... }
}

This should be fully typesafe as far as I understand, but is there any variation of this kind of shorthand that would work? I do understand that the compiler doesn't allow overriding with non-generic methods, but this is a case of replacing type arguments with wildcards. My guess is that this isn't actually supported because the compiler could just as easily support

public class IDontCareAboutSortingThingx100 implements Thing {
    @Override
    public void <T> doSomething(List<T> objects) { ... }
}

i.e. overriding with weaker bounds, but that doesn't seem to be allowed. Anyhow, just curious if anyone has a magic incantation for cases like this.


回答1:


Essentially what you're asking for is contravariant method parameters, e.g. a non-generic example looks like:

interface I {
    void m(String s);
}

class C implements I {
    @Override
    public void m(Object o) {}
}

void(Object) is a subsignature of void(String) because the widening conversion is always OK. Java doesn't have this.

For generics, you may override a generic method to be non-generic:

class NotGeneric implements Thing {
    @Override
    public void doSomething(List rawList) {}
}

But you basically shouldn't do it. You will get raw type warnings and you should listen to them. It's available for backwards compatibility.

If it were me, I would just repeat the ugly generic signature because I don't think it's all that ugly.

Something else you could do would be like

interface NonGenericThing extends Thing {
    @Override
    default <T extends Comparable<? super T>>
    void doSomething(List<T> list) {
        doSomethingImpl(list);
    }
    void doSomethingImpl(List<?> list);
}

And then you implement NonGenericThing instead and override doSomethingImpl. (Prior to Java 8, NonGenericThing must be an abstract class.)

Of course that might not be feasible if Thing is actually a large interface. You could also declare Thing this way to begin with, if it's appropriate.




回答2:


Not quite sure where you're trying to get to but couldn't you encapsulate the restrictions in a separate class?

public class It<T extends Comparable<? super T>> {

    public List<T> them;
}

public interface Thing {

    void doSomething(It<String> them);
}



回答3:


You can embed the type information into a class:

public class IDontCareAboutSortingThingx100<T extends Comparable<? super T>> implements Thing<T> {

    @Override
    public void doSomething(List<T> objects) {
    }
}


来源:https://stackoverflow.com/questions/28875950/java-generics-overriding-generic-methods-wildcard-shorthand

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!