2010-12-09 90 views
1

看看这个奇怪的问题:不明原因的字段值变化

Debugging steps

  1. 我对所有访问现场res1
  2. RES1断点分配f的价值,这是“酒吧”
  3. RES1现在 “栏中的”
  4. 下破,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> 
+0

你能发表一些代码吗? – 2010-12-09 13:07:42

+0

您是否可以将它降低到演示问题所需的最小代码量,并将代码完整发布? – NPE 2010-12-09 13:08:08

回答

4

在猜测:你在断言阶段看类的不同实例,这是通过这种奇怪的反射问题引起比你设置为“酒吧”的时候还要多。

虽然没有看到代码的其余部分,但很难说清楚。

编辑:问题是您的opsByClass缓存将包含一个操作,该操作隐含地具有关联的ServiceObject。因此,当您使用Foo创建第一个ServiceObject时,它将缓存与第一个实例ServiceObject关联的操作实例。当您在第二个ServiceObject实例上调用svc.execute时,它将查找映射中的操作,并查找与第一个实例关联的Operation ......这可能不是您想要的。

0

我猜你已经让你的代码跨越了不同的测试。
建议您在onSetUp()方法中执行设置

0

我找到了它。问题是,因为Operation不是static,它指的是它最初由其创建的ServiceObject,而不是执行第二个调用的那个。