问题描述
|
我有两节课。第一类具有
someField
,第二类需要更改,因此第一类称为FirstClass.setSomeField(value)
。第二类当时无法更改该字段,因此它将此“ 2”存储到列表中,稍后将通过该列表并应用必要的更改。该类必须以一种可以比较FutureChange
实例的方式来存储它,即避免两次将同一字段设置两次。
实现“ 2”的最佳方法是什么?通过反射,这很容易。问题是我将有数百个类,每个类都有许多字段。
我什至尝试了一个地图,其中有一个字段名开关:
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
并稍后再调用会很完美,但是我需要检查它在做什么,以便我可以比较两者并确定它们是否冲突。
解决方法
我会按照您的建议使用反射。这将比直接应用更改慢得多。如果您真的想提高效率,最好将代码分为两个阶段/阶段,一个阶段使用当前值,另一个阶段应用更改,而不是尝试存储更改。
public class StoredChanges {
private final Map<Object,Map<String,Object>> changes = new IdentityHashMap<Object,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,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();
}
}