我遇到了一个自定义泛型类型的问题,该类型具有自定义泛型子类型。
我正在尝试实现某种构建器模式,并且我希望在主方法中或多或少地使用我的语句。
任何人都可以帮助我找到一个更好的原因来声明泛型,所以我不再需要演员,我不会在语句中得到编译错误。或者任何人都可以用明文解释为什么这不起作用?
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;
}
}
答案 0 :(得分:1)
您需要演员,因为SubType
是原始类型。因此,其所有成员都是原始成员,包括从SuperType
继承的成员。 SuperType.pageSize
的原始签名是其擦除SuperType pageSize(int)
。所以“修复”不使用原始类型。这对于ConcreteType
来说都是神奇的。
修改:不要使用原始类型。永远。您应该使用ConcreteType
,但在使用重新声明每种方法的愚蠢,愚蠢,愚蠢的“解决方案”之前,请改用((SubType<?>) new SubType())
。
答案 1 :(得分:0)
我不确定失败的原因,但这是我的理解: 抽象类SuperType&gt; { public E pageSize(int value){...} }
对于方法pageSize,因为你声明为extends SuperType<E>
,在类型擦除之后,方法签名实际上是SuperType pageSize(int)
,这导致了new SubType().pageSize(0).id(10)
中的问题,因为pageSize正在返回超级类型。
虽然它看起来并不像你期望的那样神奇,但是使用协变返回类型你可以简单地“重载”继承类中的那些方法:
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);
}
}