在以下代码中,getEntriesNotWorking
方法报告编译时错误:
public class DoubleBracketInitializerTest {
class Container {}
class Entry {
Container container;
public Entry(Container container) {
this.container = container;
}
}
class DetailedContainer extends Container {
List<Entry> getEntriesNotWorking() {
return new ArrayList<Entry>() {{
add(new Entry(this)); // compile-time error mentioned below
}};
}
List<Entry> getEntriesWorking() {
return Arrays.asList(new Entry(this));
}
}
}
错误:
构造函数DoubleBracketInitializerTest.Entry(new ArrayList(){})未定义
getEntriesWorking()
方法正在正确编译。构造函数显然在那里,因为DetailedContailer
是Contailer
的子类。
这两种方法有什么区别,使代码无效?如何使双括号初始化程序适用于此类层次结构?
答案 0 :(得分:5)
双括号初始化:
return new ArrayList<Entry>() {{
add(new Entry(this)); // compile-time error mentioned below
}};
创建一个匿名内部类,在这种情况下,它是ArrayList<Entry>
的子类。因此,this
引用引用ArrayList<Entry>
的子类的实例,而不是DetailedContainer
。要获取this
类当前实例的DetailedContainer
引用,请使用DetailedContainer.this
return new ArrayList<Entry>() {{
add(new Entry(DetailedContainer.this));
}};
当然,如果您不想要固定大小的列表,可以直接使用:
return new ArrayList<Entry>(Arrays.asList(new Entry(this)));
而不是匿名类。这更容易理解。
另见:
答案 1 :(得分:3)
问题是在new ArrayList<Entry>() { ... }
内,this
是ArrayList<Entry>
。线索在错误消息中,它指定了它正在寻找的构造函数签名。
如果你真的想要使用这种初始化,你需要:
add(new Entry(DetailedContainer.this));
...引用DetailedContainer
的封闭实例。
除非你真的需要,我还强烈建议你避免内部课程。如果你只有顶级类,或者如果你真的需要嵌套静态类,那么生命就会简单得多。
我还避免使用这种匿名ArrayList
子类构造 - 与仅仅创建数组列表并添加项目相比,它比IMO更麻烦。或者使用Guava,用:
return Lists.newArrayList(new Entry(this));
全面简化!
答案 2 :(得分:1)
你可以这样做。
class DetailedContainer extends Container {
List<Entry> getEntriesNotWorking() {
return new ArrayList<Entry>(Arrays.asList(new Entry(this)));
}
List<Entry> getEntriesWorking() {
return Arrays.asList(new Entry(this));
}
}
答案 3 :(得分:1)
return new ArrayList<Entry>() {{
add(new Entry(this)); // compile-time error mentioned below
}};
您似乎正在创建匿名类实现,因此匿名类中的此关键字引用ArrayList类型的对象。 因此,由于没有包含ArrayList的Entry类的构造函数作为参数可用,因此它提供了编译错误。
答案 4 :(得分:0)
return new ArrayList<Entry>() {{
add(new Entry(this)); // compile-time error mentioned below
}};
请尝试以下方法:
ArrayList<Entry> list = new ArrayList<Entry>();
list.add(new Entry(this));
return list;