有界类型:多边界

时间:2014-04-11 13:53:26

标签: java multiple-inheritance bounded-types

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

  • T仅扩展B
  • T延伸B和I(此处为D)
  • T仅限我
  • 其他一切

所以这是代码:

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

编译器抱怨并说两件事:

  1. 不明确的电话

      

    方法句柄(Main.D)对于Main类型是不明确的   我猜这个问题是由与问题2相同的原因引起的。我明确地将T的类型限制为B和I的子类型,从而消除了我认为的模糊性。

  2. 相同的擦除句柄

      

    方法句柄(T)与Main类型中的另一种方法具有相同的擦除句柄(Main.B)   我的猜测是,这是所有问题的真正原因。 Java在运行时以某种方式删除了对我的绑定?但是当我用类型B调用方法时,这并没有调用带注释的方法。

  3. 有人可以解释我如何解决问题/区分B,B&amp; I和I?

2 个答案:

答案 0 :(得分:1)

  

Java在运行时以某种方式删除了对我的绑定?

不,Java在运行时删除每个类型信息(除了反射目的),这称为类型擦除。

使用边界编译器可以将代码转换为handle(Object)handle(B)handle(I),但在T extends B & I情况下编译器会发生冲突。

AFAIK,没有共同的约束,没有办法解决这个问题。 T extends D代替T extends B & I D extends B implements 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");
    }
}

答案 1 :(得分:0)

有一种称为类型擦除的概念适用于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");
}

实际上变成了

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

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

public static void handle(B objT) { 
    System.out.println("B+I");
}

private static void handle(I obj) {
    System.out.println("I");
}

类型变量的最左边界限是替换为该类型的参数。如您所见,第二种和第三种方法都具有相同的名称和相同的参数类型,即。相同的签名。编译器不允许这样做。

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

<T extends I & B>

无效。它也行不通,因为你的第四种方法将再次具有相同的擦除功能。

另外,调用

handle(d);

是一个问题,因为第二个和第四个方法都可以处理它,没有一个更具体。这被称为重载模糊。