考虑以下计划:
SomeClass.java:
package somepackage;
import java.util.List;
public class SomeClass implements SomeInterface {
public SomeClass(boolean add){}
public static void main(String[] args){
SomeSubclass sub1 = new SomeSubclass(false);
for (String s : sub1.getList())
System.out.println("before: " + s);
SomeSubclass sub2 = new SomeSubclass(true);
for (String s : sub1.getList())
System.out.println("after: " + s);
}
@Override
public void addToList(String s) {
someList.add(s);
}
@Override
public List<String> getList() {
return someList;
}
}
SomeSubclass.java:
package somepackage;
public class SomeSubclass extends SomeClass {
public SomeSubclass(boolean add){
super(add);
if (add)
this.addToList("a");
}
}
SomeInterface.java:
package somepackage;
import java.util.ArrayList;
import java.util.List;
public interface SomeInterface {
List<String> someList = new ArrayList<String>();
public void addToList(String s);
public List<String> getList();
}
程序运行时输出以下内容:
after: a
未发送第一个调试消息,因为SomeSubclass的第一个实例的列表为空。但是,一旦将元素添加到第二个实例的列表中,第一个实例也会添加元素。在分别使用JDK 1.8和Java SE 8编译和运行时会发生这种情况。据我所知,它不应该发生。是故意的,如果是,那么完成这项任务的正确方法是什么?
我也觉得我应该提一下这个简化代码的实际实现。我维护的API中有一个类,它实现了一个名为Metadatable的接口,该接口存储其实例的元数据映射。程序可以使用API通过方法覆盖最近快照中的此类,并且当完成此操作时,元数据有效地变为静态。毋庸置疑,这会在API发生时打破整个元数据部分。
答案 0 :(得分:3)
此处的问题是,someList
隐含static
(和final
),因为它是在界面中定义的。
界面正文中的每个字段声明都隐含
public
,static
和final
。允许为这些字段冗余地指定任何或所有这些修饰符。
整个接口只有一个someList
实例,因此所有实现类和子类都在同一个列表中运行。
你可以做以下两件事之一:
将您的界面更改为abstract
课程,以便someList
隐含static
。
将someList
的声明移至SomeClass
,这样就不会隐含static
。