Java泛型-使泛型扩展到2个接口
你是如何做到这一点的:Java泛型-使泛型扩展到2个接口,java,class,generics,interface,Java,Class,Generics,Interface,你是如何做到这一点的: public class Frankenstein<T extends IHuman, IMonster>{ } 编辑 为什么这不起作用 public <T> void mapThis( Class<? extends MyClass<T>> key, Class<? extends T & IDisposable> value) { } public void映射此( 类Reime
public class Frankenstein<T extends IHuman, IMonster>{
}
编辑
为什么这不起作用
public <T> void mapThis(
Class<? extends MyClass<T>> key, Class<? extends T & IDisposable> value) {
}
public void映射此(
类Reimeus已经指出,您在编辑中要求的是不可能的。我只想进一步说明原因
人们会认为你可以使用以下方法:
public <T, U extends T & IDisposable> void mapThis(
Class<? extends MyClass<T>> key,
Class<? extends U> value
) { ... }
<T, U extends Object & IDisposable>
现在,holder.comparator
是一个比较器
和一个比较器
Chris还指出,这是一个与此语言限制相冲突的bug。它被关闭,因为它不会修复以下评论:
如果类型变量后面可以跟类型变量或
参数化)接口,可能会有更多
递归类型的变量,很难处理
当绑定只是一个参数化类型时,已经很复杂了,
e、 g.
。因此,边界不会消失
javac和Eclipse都同意S&T
和
S&Comparable
是非法的
这些就是限制背后的原因。特别是针对泛型方法(您的问题所涉及的),我想进一步指出,类型推断在理论上会导致这样的界限毫无意义
如果我们重新检查上述假设签名中声明的类型参数:
<T, U extends T & IDisposable>
或者只是这个(细微的区别,但那是):
这可以通过相同的方式减少(Foo
可以是类或接口):
此处,T
被推断为对象
-这与前面关于简化mapThis
类型参数的推理相匹配。您必须手动指定类型参数,以实现预期的类型检查:
MyClass.<String>foo("asdf", 42); // compiler error
表发生了变化-我们必须手动放松类型参数以使其进行编译:
MyClass.<Object, Object>foo("asdf", 42); // legal
MyClass.foo(“asdf”,42);//合法
发生这种情况是因为编译器推断方法类型参数的方式有限。因此,您想要实现的实际上是一个限制调用方参数的应用程序
然而,这个问题似乎已经在Java 8中得到了解决,MyClass.foo(“asdf”,42)
现在编译没有任何错误(感谢Regent指出这一点)。我只是想分享一下我在这些(非常罕见)情况下使用的技巧:
/**
* This is a type-checking method, which gets around Java's inability
* to handle multiple bounds such as "V extends T & ContextAware<T>".
*
* @param value initial value, which should extends T
* @param contextAware initial value, which should extend ContextAware<T>
* @return a new proxy object
*/
public T blah(T value, ContextAware<T> contextAware) {
if (value != contextAware) {
throw new IllegalArgumentException("This method expects the same object for both parameters.");
}
return blah(value);
}
/**
*这是一种类型检查方法,它绕过了Java的缺陷
*处理多个边界,如“V扩展T&ContextAware”。
*
*@param value初始值,该值应扩展到T
*@param contextAware初始值,应扩展contextAware
*@返回一个新的代理对象
*/
公共T blah(T值,ContextAware ContextAware){
if(值!=contextAware){
抛出新的IllegalArgumentException(“此方法要求两个参数使用相同的对象”);
}
返回blah(值);
}
因此,通过为您试图满足的每个边界要求相同的对象,您可以得到编译时类型检查和执行所有操作的单个对象。诚然,为每个参数传递相同的对象有点愚蠢,但我在我的“内部”代码中非常安全和舒适地做到这一点。顺便说一句,可能重复,MyClass.foo(“asdf”,42)
没有给出Java 8中
边界的编译错误。@Regent很高兴看到这个问题得到了解决。更新了我的答案,谢谢!很好的答案,即使我自己没有分享。我认为这是编译器中的一个设计缺陷
<T extends Foo, U extends T & IDisposable>
<T extends Foo, U extends Foo & IDisposable>
class MyClass {
static <T> void foo(T t1, T t2) { }
}
MyClass.foo("asdf", 42); // legal
MyClass.<String>foo("asdf", 42); // compiler error
class MyClass {
static <T, U extends T> void foo(T t, U u) { }
}
MyClass.foo("asdf", 42); // compiler error
MyClass.<Object, Object>foo("asdf", 42); // legal
/**
* This is a type-checking method, which gets around Java's inability
* to handle multiple bounds such as "V extends T & ContextAware<T>".
*
* @param value initial value, which should extends T
* @param contextAware initial value, which should extend ContextAware<T>
* @return a new proxy object
*/
public T blah(T value, ContextAware<T> contextAware) {
if (value != contextAware) {
throw new IllegalArgumentException("This method expects the same object for both parameters.");
}
return blah(value);
}