考虑以下程序:
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的整个元数据部分。
这里的问题someList
是隐式static
(和final
),因为它是在接口中定义的。
JLS的9.3节规定:
在接口的身体的每一个字段声明是含蓄
public
,static
和final
。可以为此类字段多余地指定任何或所有这些修饰符。
someList
整个接口只有一个实例,因此所有实现类和子类都在同一列表上进行操作。
您可以执行以下两项操作之一:
将您的接口更改为一个abstract
类,这样someList
就不是隐式的static
。
将声明someList
移到,SomeClass
这样就不会隐式了static
。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句