1

我遇到了具有自界泛型子类型的自界泛型类型的问题。

我正在尝试实现某种构建器模式,并且我希望我的陈述或多或少类似于 main 方法。

任何人都可以帮助我找到更好的为什么要声明泛型,这样我就不再需要强制转换并且我不会在语句中遇到编译错误。或者任何人都可以用明文解释为什么这不起作用?

import java.util.Date;

public class SelfBoundingGenericTypeTest {
    public static void main(String[] args) {
        ConcreteType type = new ConcreteType().pageSize(1).id(12);

        SubType type2 = (SubType) new SubType().id(10).pageSize(0); // Why do i need the cast?

        SubType type3 = new SubType().pageSize(0).id(10); // Compile error
    }
}

abstract class SuperType<E extends SuperType<E>> {
    private int _pageSize = Integer.MIN_VALUE;
    private int _startIndex = Integer.MIN_VALUE;

    @SuppressWarnings("unchecked")
    public E pageSize(int value) {
        this._pageSize = value;
        return (E) this;
    }

    @SuppressWarnings("unchecked")
    public E startIndex(int value) {
        this._startIndex = value;
        return (E) this;
    }

    public int getPageSize() {
        return _pageSize;
    }

    public int getStartIndex() {
        return _startIndex;
    }
}

class SubType<E extends SubType<E>> extends SuperType<E> {
    private long _id = Long.MIN_VALUE;

    @SuppressWarnings("unchecked")
    public E id(long value) {
        this._id = value;
        return (E) this;
    }

    public long getId() {
        return _id;
    }
}

class ConcreteType extends SubType<ConcreteType> {
    private Date _startDate;

    public Date getStartDate() {
        return _startDate;
    }

    public ConcreteType startDate(Date value) {
        this._startDate = value;
        return this;
    }
}
4

2 回答 2

1

您需要演员阵容,因为SubType它是原始类型。因此,它的所有成员都是原始的,包括那些继承自SuperType. 的原始签名SuperType.pageSize是它的擦除SuperType pageSize(int)。所以“修复”是不使用原始类型。这一切都将神奇地为ConcreteType.

编辑:不要使用原始类型。曾经。你应该使用你的ConcreteType,但在你使用重新声明每种方法的愚蠢、愚蠢、愚蠢的“解决方案”之前,请((SubType<?>) new SubType())改用。

于 2012-08-28T08:50:39.210 回答
0

我不太确定失败的原因,但这是我的理解: abstract class SuperType> { public E pageSize(int value) { ...} }

对于方法 pageSize,因为您将 E 声明为extends SuperType<E>,在类型擦除之后,方法签名实际上是SuperType pageSize(int),这导致了问题,new SubType().pageSize(0).id(10)因为 pageSize 返回一个 SuperType。

尽管它看起来不像您期望的那么神奇,但使用协变​​返回类型,您可以简单地“重载”继承类中的这些方法:

import java.util.Date;

public class SelfBoundingGenericTypeTest {
    public static void main(String[] args) {
        ConcreteType type = new ConcreteType().pageSize(1).id(12);

        SubType type2 = new SubType().id(10).pageSize(0); // works fine now

        SubType type3 = new SubType().pageSize(0).id(10); // works fine too
    }
}

abstract class SuperType {
    private int _pageSize = Integer.MIN_VALUE;
    private int _startIndex = Integer.MIN_VALUE;

    public SuperType pageSize(int value) {
        this._pageSize = value;
        return this;
    }

    public SuperType startIndex(int value) {
        this._startIndex = value;
        return this;
    }

    public int getPageSize() {
        return _pageSize;
    }

    public int getStartIndex() {
        return _startIndex;
    }
}

class SubType extends SuperType {
    private long _id = Long.MIN_VALUE;

    public SubType id(long value) {
        this._id = value;
        return this;
    }

    public SubType pageSize(int value) {
        return (SubType) super.pageSize(value);
    }

    public SuperType startIndex(int value) {
        return (SubType) super.pageSize(value);
    }

    public long getId() {
        return _id;
    }
}

class ConcreteType extends SubType {
    private Date _startDate;

    public Date getStartDate() {
        return _startDate;
    }

    public ConcreteType startDate(Date value) {
        this._startDate = value;
        return this;
    }

    public ConcreteType id(long value) {
        return (ConcreteType) super.id(value);
    }

    public ConcreteType pageSize(int value) {
        return (ConcreteType) super.pageSize(value);
    }

    public ConcreteType startIndex(int value) {
        return (ConcreteType) super.pageSize(value);
    }

}
于 2012-08-28T09:06:11.657 回答