Java泛型类构造函数的调用

3
我有以下代码:

我有以下代码:

public class A {}

public class B extends A {}

public class C <T extends A> {

  private final T data;

  public C(final T data) {
    this.data = data;
  }
}

public class D<T extends B> extends C<T> {

  public D(T data) {
    super(data);
  }

  public D() {
    this(new B());
  }

  public static D<B> create() {
    return new D(new B());
  }
}

类D中存在编译错误:

error: no suitable constructor found for D(B)
    this(new B());
constructor D.D() is not applicable
  (actual and formal argument lists differ in length)
constructor D.D(T) is not applicable
  (actual argument B cannot be converted to T by method invocation conversion)
where T is a type-variable:
T extends B declared in class D

让我困惑的是,静态方法D.create()基本上也做了同样的事情,但却编译没有任何错误。有人能解释这个错误吗?以及D()和D.create()之间的区别是什么?


1
通过将一字母类名与按照惯例仅使用一个字母的泛型类型混合使用,您将会让所有人感到困惑。 - artbristol
2个回答

4
错误出现的原因是对于类 D,并不知道类型会是 B,只知道泛型类型会 扩展 B ——你假设它将是 B,因为在你的类层次结构中还没有其它类(这是编译器必须考虑未来可能发生变化的事实)。
请注意,在工厂方法中,您正在实例化 D原始 类型(没有泛型参数)。相反,应提供一种类型:
您应该更改:
public static D<B> create() {
    return new D(new B());
}

to:

public static D<B> create() {
    return new D<B>(new B()); // Note: Added generic parameter <B>
}

1
因为类 D 的泛型类型 T 没有绑定。
这将起作用。
public class E extends D<B> {

    public E() {
        super(new B()); // call to D's constructor public D(T data)
    }
}

通常你会以这种方式调用 D 的构造函数:

new D<B>(new B());

但是你不能这样做。
public D() {
    this<B>(new B());
}

另一个例子。

稍微改一下代码,你就会看到问题所在。

class BBB extends B {
}

class C<T extends A> {

    protected final T data;

    public C(final T data) {
        this.data = data;
    }
}

class D<T extends B> extends C<T> {

    public D() {
        this(new B());
    }

    public T getData(){
        return data;
    }
}

D<BBB> dOfBBB = new D<BBB>();
BBB data = dOfBBB.getData(); // So if this(new B()) would work 
                              // how can the data then be returned?
                              // Because BBB is returned but it would be 
                              // initialized with only a B instance

谢谢您的解释。这是否意味着,如果我想保持类D的泛型(以便将来能够像C→D一样扩展它),我只能使用D.create() - 我的意思是没有办法无错误地重写D()? - Petr
@Petr 是的,在你的情况下,我会遵循 Bohemian 的答案。 - René Link

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接