Java Generics:覆盖泛型方法,通配符速记?

时间:2015-03-05 10:45:06

标签: java generics

如果我有一个带有如下通用方法的接口:

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

我在某些地方需要那些丑陋的泛型类型规范,但大多数实现实际上并不需要它:

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) { ... }
}

我想写的是:

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

据我所知,这应该是完全类型安全的,但是这种速记的变化是否有效?我确实理解编译器不允许覆盖非泛型方法,但这是用通配符替换类型参数的情况。我的猜测是实际上并不支持,因为编译器可以轻松支持

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

即。覆盖较弱的界限,但似乎不允许这样做。无论如何,只是好奇,如果有人对这样的案件有一个神奇的咒语。

3 个答案:

答案 0 :(得分:4)

不太确定你要去哪里,但是你不能将这些限制封装在一个单独的类中吗?

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

    public List<T> them;
}

public interface Thing {

    void doSomething(It<String> them);
}

答案 1 :(得分:1)

基本上你要求的是逆变方法参数,例如:非通用示例如下所示:

interface I {
    void m(String s);
}

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

void(Object)void(String)的子签名,因为扩展转换始终可以。 Java没有这个。

对于泛型,可能覆盖泛型方法为非泛型:

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

但你基本上不应该这样做。您将获得raw type warnings,您应该听取他们的意见。它可用于向后兼容。

如果是我,我会重复丑陋的通用签名,因为我不认为这一切都很难看。

你可以做的其他事情就像

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

然后您实施NonGenericThing并覆盖doSomethingImpl。 (在Java 8之前,NonGenericThing必须是抽象类。)

当然,如果Thing实际上是一个大型接口,这可能是不可行的。如果合适的话,你也可以用这种方式宣布Thing

答案 2 :(得分:0)

您可以将类型信息嵌入到类

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

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