我有两节课。第一个类有someField
,第二个类需要更改,所以第一个类调用FirstClass.setSomeField(value)
。第二个类不能在那一刻更改字段,因此它将此FutureChange
存储到一个列表中,该列表将在稍后时间进行并应用必要的更改。该类必须以可以比较FutureChange
的实例的方式存储它,即避免两次设置相同的字段,以及其他事项。
实施FutureChange
的最佳方式是什么?通过反射,这很容易。问题是我将有数百个类,每个类都有很多字段。
我甚至尝试了一个带有字段名称开关的地图:
public class Example {
public static Integer number;
public static String words;
public static void main(String args[]) {
Map<Field, Object> map = new HashMap<Field, Object>();
// store modifications
map.put(Field.number, new Integer(10));
map.put(Field.words, "Words");
// some time later
for(Map.Entry<Field, Object> entry: map.entrySet()) {
modify(entry.getKey(), entry.getValue());
}
}
public static void modify(Field m, Object value) {
switch(m){
case number:
number = (Integer) value;
break;
case words:
words = (String) value;
break;
}
}
public enum Field {
number,
words;
}
}
但这不是最有效的方式,并且随着课程变大而可能会被堵塞。有谁知道如何最好地实现这个?
更多代码:
public class Main {
FirstClass a = new FirstClass();
SecondClass b = new SecondClass();
// Third, Fourth, etc.
public static void main(String args[]) {
while(true) {
// run each, no modifications allowed
a.run(); // may want to modify several variables of b
b.run(); // same as above
// end of all runs, now modify
a.modifyAll();
b.modifyAll();
}
}
}
如您所见,我必须在运行期间存储它,然后再执行。
存储匿名内部Callable
并稍后调用将是完美的,但我需要检查它正在做什么,以便我可以比较两个并确定它们是否存在冲突。
答案 0 :(得分:0)
我会按你的建议使用反射。这比直接应用更改要慢得多。如果您真的想要效率,最好将代码分成两个阶段/阶段,一个使用当前值,一个应用更改而不是尝试存储更改。
public class StoredChanges {
private final Map<Object, Map<String, Object>> changes = new IdentityHashMap<Object, Map<String, Object>>();
public void storeChange(Object o, String fieldName, Object value) {
Map<String, Object> changedForObject = changes.get(o);
if (changedForObject == null)
changes.put(o, changedForObject = new LinkedHashMap<String, Object>());
changedForObject.put(fieldName, value);
}
public void applyChanges() {
for (Map.Entry<Object, Map<String, Object>> objectMapEntry : changes.entrySet()) {
Object o = objectMapEntry.getKey();
for (Map.Entry<String, Object> fieldChange : objectMapEntry.getValue().entrySet()) {
String fieldName = fieldChange.getKey();
try {
Method setter = o.getClass().getMethod("set" + Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1));
setter.invoke(o, fieldChange.getValue());
} catch (Exception e) {
e.printStackTrace(); // or log it.
}
}
}
changes.clear();
}
}