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);
    }