Class java 泛型的层次结构问题

Class hierarchy problem with java generics

我 运行 遇到通用函数中 class 层次结构的问题。 我需要强制执行,在函数中指定两个 classes TU,一个是另一个的 child。 令我惊讶的是,<T extends U> 结构根本没有强制执行 UT 的 parent child 关系。 相反,它还允许 TU 是同一类型。

这会产生一个问题,因为看起来 U extends T Java 不会指示错误,而是会愉快地推断出 objects 都是类型 T(毫无疑问,这是真的)然后毫无怨言地编译和 运行 代码。

这是一个说明问题的示例:

public class MyClass {
    public static void main(String args[]) {
      Foo foo = new Foo();
      Bar bar = new Bar();

      // This code is written as intended
      System.out.println( justTesting(foo, bar) );

      // This line shouldn't even compile
      System.out.println( justTesting(bar, foo) );
    }
    
    static interface IF {
       String get(); 
    }
    
    static class Foo implements IF {
       public String get(){return "foo";} 
    }
    
    static class Bar extends Foo {
        public String get(){return "bar";}
        
    }
    
    static <G extends IF , H extends G> String justTesting(G g, H h) {
        if (h instanceof G)
            return h.get() + " (" + h.getClass() + ") is instance of " + g.getClass() + ". ";
        else
            return "it is the other way round!";
    }
}

这是输出:

bar (class MyClass$Bar) is instance of class MyClass$Foo. 
foo (class MyClass$Foo) is instance of class MyClass$Bar. 

我需要确保编译器观察到泛型 classes 的 parent child 关系。有什么办法吗?

可以编译,因为 IFboth H and G.

意思是:泛型并不像我们想象的那样“动态”,我们也可以这样写:

static <G extends IF, H extends IF> ... // just pointing out that G *could* differ from H 

无视空检查,这是你想要的吗:

  static <G extends IF, H extends G> String justTesting(G g, H h) {
    if (g.getClass().isAssignableFrom(h.getClass())) {
      return h.get() + " (" + h.getClass() + ") is instance of " + g.getClass() + ". ";
    } else {
      return "it is the other way round!";
    }
  }

?

Class.isAssignableFrom()


打印:

bar (class com.example.test.generics.Main$Bar) is instance of class com.example.test.generics.Main$Foo. 
it is the other way round!

注意“匿名类”,例如:

System.out.println(
  justTesting(
    new IF() {
      @Override
      public String get() {
        return "haha";
      }
    }, foo)
);

System.out.println(
  justTesting(
    foo, new IF() {
      @Override
      public String get() {
        return "haha";
      }
    }
  )
);

同时打印“这是相反的方向!”,所以这里的决定不是那个“二进制”。