Java泛型:覆盖泛型方法,通配符shorthand?
Java Generics: Overriding generic methods, wildcard shorthand?
如果我有一个带有如下通用方法的接口:
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) { ... }
}
据我所知,这应该是完全类型安全的,但是这种 shorthand 有任何变体可以工作吗?我知道编译器不允许用非泛型方法覆盖,但这是用通配符替换类型参数的情况。我的猜测是这实际上不受支持,因为编译器可以很容易地支持
public class IDontCareAboutSortingThingx100 implements Thing {
@Override
public void <T> doSomething(List<T> objects) { ... }
}
即用较弱的界限覆盖,但这似乎是不允许的。无论如何,只是好奇是否有人对这种情况有神奇的咒语。
不太确定你想去哪里,但你不能把限制封装在一个单独的 class 中吗?
public class It<T extends Comparable<? super T>> {
public List<T> them;
}
public interface Thing {
void doSomething(It<String> them);
}
您可以将类型信息嵌入到 class:
public class IDontCareAboutSortingThingx100<T extends Comparable<? super T>> implements Thing<T> {
@Override
public void doSomething(List<T> objects) {
}
}
本质上你要求的是逆变方法参数,例如一个非通用示例如下所示:
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
。 (在Java8之前,NonGenericThing
必须是一个摘要class。)
当然,如果Thing
实际上是一个大接口,那可能不可行。如果合适,您也可以以这种方式开始声明 Thing
。
如果我有一个带有如下通用方法的接口:
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) { ... }
}
据我所知,这应该是完全类型安全的,但是这种 shorthand 有任何变体可以工作吗?我知道编译器不允许用非泛型方法覆盖,但这是用通配符替换类型参数的情况。我的猜测是这实际上不受支持,因为编译器可以很容易地支持
public class IDontCareAboutSortingThingx100 implements Thing {
@Override
public void <T> doSomething(List<T> objects) { ... }
}
即用较弱的界限覆盖,但这似乎是不允许的。无论如何,只是好奇是否有人对这种情况有神奇的咒语。
不太确定你想去哪里,但你不能把限制封装在一个单独的 class 中吗?
public class It<T extends Comparable<? super T>> {
public List<T> them;
}
public interface Thing {
void doSomething(It<String> them);
}
您可以将类型信息嵌入到 class:
public class IDontCareAboutSortingThingx100<T extends Comparable<? super T>> implements Thing<T> {
@Override
public void doSomething(List<T> objects) {
}
}
本质上你要求的是逆变方法参数,例如一个非通用示例如下所示:
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
。 (在Java8之前,NonGenericThing
必须是一个摘要class。)
当然,如果Thing
实际上是一个大接口,那可能不可行。如果合适,您也可以以这种方式开始声明 Thing
。