看一下这个奇怪的问题:
我在对字段res1
的所有访问上都有一个断点
Res1分配了f的值,即“ bar”
Res1现在是“栏”
在下一个中断处,res1突然是null
为什么这不可能呢?
由于res1的断点,我可以看到它根本不应该更改
而且不能,因为我没有在赋值和assertEquals
之间显式更改它,并且此代码在单个JUnit线程中运行。
没有其他名为res1
的字段或变量。
可能是什么?我假设这不是JVM中的错误,但谁知道。
正如Jon Skeet所说,问题在于实例不同。这是由以下奇怪的反射问题引起的:
public class ServiceObject {
private static final Map<Class<?>, Map<String, Operation>> opsByClass =
new ConcurrentHashMap<Class<?>, Map<String,Operation>>();
private final Object target;
private final Map<String, Operation> myClassOps;
private class Operation {
private final Method method;
public Operation(Method met) {
this.method = met;
method.setAccessible(true);
}
public void execute(Map<String,?> args, Responder responder, Object context, boolean coerce) {
...
method.invoke(target, mArgs);
}
}
public ServiceObject(Object target) {
Class<?> myClass = target.getClass();
Map<String, Operation> op = opsByClass.get(myClass);
if (op == null) {
op = new HashMap<String, Operation>();
for (Method meth : myClass.getMethods()) {
...
op.put(opName, new Operation(meth));
}
opsByClass.put(myClass, op);
}
this.target = target;
this.myClassOps = op;
}
public void execute(String opName) {
Operation op = myClassOps.get(opName);
...
op.execute(args, responder, context, coerce);
}
}
// Foo is equivalent to the class that contains <res1> above
class Foo {
@ServiceOperation
public void bar() {
// breakpoint here
}
}
运行测试时会发生什么:
a = new Foo();
b = new Foo();
svc = new ServiceObject(a);
svc.execute("bar", ...); // inside Foo.bar() <this> will be <a>
svc = new ServiceObject(b);
svc.execute("bar", ...); // inside Foo.bar() <this> will still be <a>, but should be <b>
最佳答案
猜测:您在断言阶段正在查看的类实例与在将其设置为“ bar”时的实例不同。
但是,如果不看其余的代码,很难说出来。
编辑:问题是您的opsByClass
缓存将包含一个操作,该操作隐式具有关联的ServiceObject
。因此,当使用ServiceObject
创建第一个Foo
时,它将缓存与ServiceObject
的第一个实例关联的Operation实例。当您在svc.execute
的第二个实例上调用ServiceObject
时,它将在映射中查找操作,并找到与第一个实例相关联的Operation
...这可能不是您想要的。