Java 有界类型:多个界

Java 有界类型:多个界,java,multiple-inheritance,bounded-types,Java,Multiple Inheritance,Bounded Types,我已经阅读了这篇文章,并试图找出如何使用绑定类型。我试图实现的是一种参数化方法,它可以处理四种不同的情况: T仅扩展B T扩展B和I(此处为D) 我只是 其他一切 下面是代码: public class Main { public static void main(String... args) { B b = new B(); D d = new D(); I i = new I() { }; han

我已经阅读了这篇文章,并试图找出如何使用绑定类型。我试图实现的是一种参数化方法,它可以处理四种不同的情况:

  • T仅扩展B
  • T扩展B和I(此处为D)
  • 我只是
  • 其他一切
下面是代码:

public class Main {

    public static void main(String... args) {
        B b = new B();
        D d = new D();
        I i = new I() {
        };
        handle("aaasd");
        handle(b);
        handle(d); <---- Problem 1
        handle(i);
    }

    public static class B {

    }

    public static interface I {

    }

    public static class D extends B implements I {

    }


    public static <T> void handle(T objT) {
        System.out.println("T");
    }

    private static <T extends B> void handle(T obj) {
        System.out.println("B");
    }

    public static <T extends B & I> void handle(T objT) { <--- Problem 2
        System.out.println("B+I");
    }

    private static <T extends I> void handle(T obj) {
        System.out.println("I");
    }
}
公共类主{
公共静态void main(字符串…参数){
B=新的B();
D=新的D();
I=新I(){
};
句柄(“aaasd”);
手柄(b);
手柄(d);
Java在运行时以某种方式删除了对I的绑定

不,Java会在运行时删除所有类型信息(反射目的除外),这称为类型擦除

使用边界,编译器将能够将代码转换为
handle(Object)
handle(B)
handle(I)
,但在
T extends B&I
的情况下,编译器会遇到冲突

好吧,如果没有一个公共边界,就无法解决这个问题,例如,
T扩展D
而不是
T扩展B&I
,其中
D扩展B实现I
,或者更改方法名称或添加另一个参数

另一种方法可能是将B+I案例中的逻辑添加到B或I方法中,并检查其中的第二个条件,例如

private static <T extends B> void handle(T obj) {
    if( obj instanceof I) { 
      System.out.println("B+I");
    }
    else {
      System.out.println("B");
    }
}
private静态无效句柄(T obj){
if(obj instanceof I){
系统输出打印项次(“B+I”);
}
否则{
系统输出打印项次(“B”);
}
}

有一个称为类型擦除的概念,适用于Java中的所有泛型。对于泛型方法,编译后,字节码中的方法显示为它们的擦除,因此

public static <T> void handle(T objT) {
    System.out.println("T");
}

private static <T extends B> void handle(T obj) {
    System.out.println("B");
}

public static <T extends B & I> void handle(T objT) { <--- Problem 2
    System.out.println("B+I");
}

private static <T extends I> void handle(T obj) {
    System.out.println("I");
}
类型变量最左边的边界是该类型的参数被替换的对象。如您所见,第二个和第三个方法都具有相同的名称和参数类型,即相同的签名。编译器不允许这样做

但是,边界的语法强制您在任何接口类型之前提供类类型

<T extends I & B>

这是一个问题,因为第2个和第4个方法都可以处理它,没有一个更具体。这被称为重载歧义。

如果你想要最后3个
处理
方法,你就不能解决它。那么还有其他方法可以解决这个问题吗?Java为什么要对我这样做…谢谢。而且在方法内部检查并不是很好d选项。用户可能会决定“将其视为
B
,而不是
B&I
。我的公共绑定问题是,我希望从没有这些公共类型的内置API中接受对象。(可能是新的编码标准?始终创建一个抽象类,充当公共类型,类似于绑定组?)@WorldSEnder很多人认为Java泛型遗漏了很多东西,但总是存在向后兼容性问题,这使得每个人都很难找到正确的方法。如果它是一个API,用户应该能够决定调用哪个API,那么您可以重命名该方法,或者只提供
handle(B)
handle(I)
每当用户传入一个将应用于两者的对象时,让调用者使用强制转换来决定。
<T extends I & B>
handle(d);