有时在我的代码中,我想引用(我认为的)泛型层次结构中的隐式类型(基本上是第一个隐含的类型?在下面)。
public class Foo<BAR extends Bar<?>> {
public void t(BAR x) {
List l = new ArrayList();
Object baz = x.makeBaz(null);
l.add(baz);
x.setBazList(l);
}
}
public interface Bar<BAZ extends Number> {
public BAZ makeBaz(Object arg1);
public List<BAZ> getBazList();
public void setBazList(List<BAZ> baz);
}
例如,在上面的代码中,可以替换行
List l = new ArrayList();
Object baz = x.makeBaz(null);
使用泛型的东西?
我宁愿避免写:
public class Foo<BAZ extends Number, BAR extends Bar<BAZ>> {
public void t(BAR x) {
List<BAZ> l = new ArrayList<BAZ>();
BAZ baz = x.makeBaz(null);
l.add(baz);
}
}
因为强制执行任何派生类的声明会感觉不自然。
我知道上面的内容有点人为,但它比试图显示我正在查看的实际代码要简单得多。
答案 0 :(得分:3)
我想主要的问题是你需要以某种方式强制你从x.makeBaz()
获得的类型与你给x.setBazList(l)
的列表的类型参数相同,如果你只是使用?
你失去了执行能力,所以你需要一个泛型类型参数。但从某种意义上说,类型参数只需要在这几行中“本地”,而其他类不需要知道。
您可以使用类型参数BAZ
来仅参数化方法而不是类:
public <BAZ extends Number> void t2(Bar<BAZ> x) {
List<BAZ> l = new ArrayList<BAZ>();
BAZ baz = x.makeBaz(null);
l.add(baz);
x.setBazList(l);
}
这用于本地化我们需要此临时类型变量BAZ
的代码区域。请注意,此方法的签名实际上是public void t2(Bar<?> x)
,即外部不需要知道此BAZ
。
现在,此方法现在接受所有Bar<anything>
而非BAR
。如果这是一个问题,你可以“包装”上面的方法。我们没有遇到与以前相同的问题,因为所有BAZ
内容都已包含在t2()
中,需要Bar<anything>
,因此我们可以安全地传递BAR
:
public void t(BAR x) {
t2(x);
}
我同意这似乎有点迂回。也许其他人会想出更好的方法。
答案 1 :(得分:0)
您可以至少绑定到数字,因为BAZ扩展数字
public class Foo<BAR extends Bar<?>> {
public void t(BAR x) {
List<Number> l = new ArrayList<Number>();
Number baz = x.makeBaz(null);
l.add(baz);
// l.add(Integer.valueOf(1)); compiles but with this here the next line throws ClassCastException
x.setBazList(l);
}
}
public interface Bar<BAZ extends Number> {
public BAZ makeBaz(Object arg1);
public List<BAZ> getBazList();
public void setBazList(List<BAZ> baz);
}
public class BarConcreate implements Bar<BigDecimal>{
long counter = 1;
private List<BigDecimal> list = new ArrayList<BigDecimal>();
public List<BigDecimal> getBazList() {
return list;
}
public BigDecimal makeBaz(Object arg1) {
return BigDecimal.valueOf(counter++);
}
public void setBazList(List<BigDecimal> baz) {
list = baz;
for(BigDecimal d : baz){
logger.debug("value:" + d.toString());
}
}
}
public void TestFooBar(){
Foo<Bar<BigDecimal>> foo = new Foo<Bar<BigDecimal>>();
Bar<BigDecimal> bar = new BarConcreate();
foo.t(bar);
}
这个java编译并运行,如果List只用BigDecimal填充,如果List中有一个整数,每个东西都可以工作,我们在x.setBazList(l)行上得到一个类转换异常;
我觉得非常有趣。
答案 2 :(得分:0)
如果你愿意,我会选择这个:
List<Number> l = new ArrayList<Number>();
Number baz = x.makeBaz(null);
希望这有帮助。
编辑:这也是有道理的:
public class Foo<BAR extends Bar<? extends Number>>