给出以下抽象类:
public abstract class BaseVersionResponse<T extends BaseVO> {
public abstract void populate(T versionVO);
}
以及以下子类:
public class VersionResponseV1 extends BaseVersionResponse<VersionVOV1>
{
protected String testFieldOne;
protected String testFieldTwo;
public String getTestFieldOne() {
return testFieldOne;
}
public void setTestFieldOne(String value) {
this.testFieldOne = value;
}
public String getTestFieldTwo() {
return testFieldTwo;
}
public void setTestFieldTwo(String value) {
this.testFieldTwo = value;
}
@Override
public void populate(VersionVOV1 versionVO) {
this.setTestFieldOne(versionVO.getFieldOne());
this.setTestFieldTwo(versionVO.getFieldTwo());
}
我希望通过调用方法执行类似的操作:
public void getVersionInfo(String version) {
BaseVO versionVO = null;
BaseVersionResponse<? extends BaseVO> baseVersionResponse = null;
baseVersionResponse = createVersionResponse(version);
versionVO = createVersionVO(version);
baseVersionResponse.populate(versionVO);
}
其中createVersionResponse(...)
和createVersionVO(...)
如下所示:
public BaseVersionResponse<? extends BaseVO> createVersionResponse(String version) {
BaseVersionResponse<? extends BaseVO> specificVersionResponse = null;
if (version.equalsIgnoreCase("V1")) {
specificVersionResponse = new VersionResponseV1();
} else if (version.equalsIgnoreCase("V2"))
specificVersionResponse = new VersionResponseV2();
return specificVersionResponse;
}
public BaseVO createVersionVO(String version) {
BaseVO versionVO = null;
if (version.equalsIgnoreCase("V1")) {
versionVO = new VersionVOV1();
} else if (version.equalsIgnoreCase("V2"))
versionVO = new VersionVOV2();
return versionVO;
}
和VersionVOV1如下所示:
public class VersionVOV1 extends BaseVO {
private String fieldOne = null;
private String fieldTwo = null;
private String fieldThree = null;
public String getFieldOne() {
return fieldOne;
}
public void setFieldOne(String fieldOne) {
this.fieldOne = fieldOne;
}
public String getFieldTwo() {
return fieldTwo;
}
public void setFieldTwo(String fieldTwo) {
this.fieldTwo = fieldTwo;
}
public String getFieldThree() {
return fieldThree;
}
public void setFieldThree(String fieldThree) {
this.fieldThree = fieldThree;
}
}
当我尝试编译这行代码时出现了问题:
baseVersionResponse.populate(versionVO);
getVersionInfo(...)
中的。我收到的消息看起来像这样:
BaseVersionResponse类型中填充(捕获#3-of?)的方法不适用于参数(BaseVO)
上面的populate
方法。
我的想法(显然是不正确的)因为baseVersionResponse在代码中的这一点实际上是一个特定的子实例,所以该类确切地知道从该特定子类调用哪个populate方法。
我在这里做错了什么?如果这不是正确的方法,有更好的方法吗?
感谢您的时间!
答案 0 :(得分:1)
如果你只是取出类型的捕获(&#34;&lt;?&gt;&#34;),并且不加以检查,它应该可以正常工作。即使使用Object类型也会编译。
但是,根据您的具体示例,您可能需要的是方法:
public BaseVersionResponse<?> createVersionResponse(String version)
更改为:
public BaseVersionResponse<? extends BaseVO> createVersionResponse(String version)
然后,而不是使用
BaseVersionResponse<?>
使用
BaseVersionResponse<? extends BaseVO>
因为您知道返回类型将是实现接口/类的那些东西之一。
答案 1 :(得分:1)
好的,我今天好好看看这个。问题在于,通配符虽然是正确的方法,但却阻止了您的操作:
BaseVO versionVO = createVersionVO(version);
因为populate
调用想要一个BaseVO的扩展名,而不是一个不符合条件的实际BaseVO。这意味着您无法直接传递该versionVO变量。
所以,为了保持类型检查到位,我认为这样做很好,因为你总是想要一个实现,几乎把所有内容保留在上面,并将你的BaseVersionResponse
类更改为:< / p>
public abstract class BaseVersionResponse<T extends BaseVO> {
public T getVersion(BaseVO versionVO) {
try {
return (T) versionVO;
} catch (ClassCastException e) {
throw new IllegalArgumentException();
}
}
public abstract void populate(BaseVO versionVO);
}
因此,populate方法现在需要一个BaseVO,并且有一个新的getVersion方法为我们做一些显式的转换。这应该没问题,因为我们知道工厂将始终提供正确的东西,但如果另一个调用者没有,则抛出IllegalArgumentException
。
现在,在响应类实现中,相应地更改populate方法:
public void populate(BaseVO version) {
VersionVOV1 versionVO = getVersion(version);
this.setTestFieldOne(versionVO.getFieldOne());
this.setTestFieldTwo(versionVO.getFieldTwo());
}
所以,我们已经改变了populate方法以获取BaseVO,并且getVersion方法为我们进行了转换。所有其他类型的检查仍然适用,我们很高兴。
铸造使它感觉不那么干净,但对于你正在使用的工厂方法,它实际上是唯一的方法(我能想到)保持类型声明和代码模式的保证。< / p>
希望有所帮助!