Java循环泛型

Mik*_*ike 5 java generics

我在理解Java泛型方面遇到了问题,我已经简化为这个例子了

class A<T extends B> {

    public void fun(T t) {

    }
}

class B {
    A a;

    public void event() {
        a.fun(this);
    }

}
Run Code Online (Sandbox Code Playgroud)

问题是这会产生警告,因为A在B中定义但A已经将其用作泛型类型.

我的第一直觉是我的设计错了,但在这种情况下我无法改变它.A就像一个集合,B就像集合中的一个节点,用户应该覆盖它.某些事件可能发生在B中,需要向父母A报告.

但由于A一般用B定义,如何避免B.event()中的编译警告

谢谢

Lau*_*ves 13

问题是你在这一行上使用的是原始类型:

A a;
Run Code Online (Sandbox Code Playgroud)

您需要为A的类型参数(T)指定类型.

你可以这样做:

A<B> a;
Run Code Online (Sandbox Code Playgroud)

但是如果我理解你对这个问题的陈述,那么A根本就不是通用的.你可能想做这样的事情:

class A<T> {
  public void fun(T t) {

  }
}

class B<T extends B<T>> {
  A<B<T>> a;
  public void event() {
    a.fun(this);
  }
}    
Run Code Online (Sandbox Code Playgroud)

甚至这个:

class A<T extends B<? extends T>> {
  public void fun(T t) {

  }
}

class B<T extends B<T>> {
  A<? super B<T>> a;
  public void event() {
    a.fun(this);
  }
}
Run Code Online (Sandbox Code Playgroud)

这些之间存在一些可能有用的变化.后一个例子是最通用的(但显然也是最复杂的).

class A<T extends B<? extends T>>是确保类型参数A是B.由于B本身是通用的,并且具有循环类型的参数,你最终需要说B<? extends T>(只是说T将在这里工作).

class B<T extends B<T>>,你可以得到在Java模拟一个"自我型"是接近.这让B谈论自己的(几乎)具体的子类型.当继承B时,你会说" class C extends <B<C>>" 这样的东西.这很有用,因为现在的类型C.a实际上是A<? super B<C>>.

? super后一个示例中的位仅在您计划将B连接到A不完全相同类型的B时才有用B.用具体的方式思考,假设你有一个A<Shape>和一个Circle(扩展Shape哪个扩展B).超级通配符允许您一起使用它们.没有它你需要一个A<Circle>而不是A<Shape>你的Circle.


Dav*_*vis 11

public class A<T extends B> {
    public void fun(T t) {
    }
}

public class B {
    A<B> a;

    public void event() {
        a.fun(this);
    }
}
Run Code Online (Sandbox Code Playgroud)

警告被打败了.

原因

A应使用特定的类类型声明类型的变量,如泛型类signature(A<T extends B>)所示.

解析度

虽然这解决了编译器警告,但潜在的问题仍然存在.劳伦斯为核心问题提供了出色的解释和解决方案.