-5

我有一个真正奇怪的问题。(非常重要的说明:这是一个示例,因为我无法粘贴原始代码,我将其编写为没有编译器的文本。)我有 2 个类:

class B {
    private int num = 9;

    public int getNum(){
       return num;
    }

    public void setNum(int num){
       this.num = num;
    }
}

class A {
    private B b = new B();

    public void setB(B b){
        b.setNum(b != null? b.getNum() : 8);
   }

   public B getB(){
       if (b == null)
           System.out.println("How possible?");
       return b;
   }
}

现在,有时我会打印出来……但我不明白这怎么可能。

A 是一个序列化的类,但我无法弄清楚。

4

7 回答 7

5

这是不可能的,不。A.getB()当您尝试编译它时,您会在定义中遇到类型错误,并且您的定义A.setB()看起来也很可疑(阴影b)。

于 2009-10-08T08:20:34.257 回答
3

有几种情况b可能为空:

  • 反射。b可能会反射性地设置为 null,从而绕过您的设置器。
  • 自定义序列化。b可能会显式恢复为 null。或者,如果B不可序列化,则将其标记为瞬态以避免错误,并且不会恢复。

要验证简单的序列化工作流程,请使用以下代码:

    Object object = "someString";

    ByteArrayOutputStream holder = new ByteArrayOutputStream();
    new ObjectOutputStream(holder).writeObject(object);

    Object readObject = new ObjectInputStream(new ByteArrayInputStream(holder.toByteArray())).readObject();

    System.out.println(readObject);

其中第一行替换为您要测试的实际对象

于 2009-10-08T08:42:12.217 回答
2

If you manage to serialize an instance of A which has b == null, then you get a NPE. The reason is that during de-serialization, the constructor isn't invoked and therefore, private B b = new B(); isn't run, so b stays null.

于 2009-10-08T08:33:31.900 回答
1

Did you serialize the instance of A before adding the initialization of B to the class?
If that is the case you could get an instance of A where b is null because the constructors are not called (initializing a member of the class is part of the implicit constructor).
Then you will need to add an implementation of readObject() to class A there you can check whether or not b is null and initialize it if necessary.

于 2009-10-08T08:35:00.913 回答
0

此行也不会编译:

b.setNum(b != null? b.getNum : new B());
于 2009-10-08T08:23:37.637 回答
0

那么,这个呢?如果给 B 作为参数,为什么不使用它呢?

class A {
    private B b = new B();

    public void setB(B b){
        if(b != null) {
            this.b = b;
        }
   }

   public B getB(){
       return b;
   }
}
于 2009-10-08T08:25:17.767 回答
0

只是一个想法:替换

System.out.println("How possible?");

new Exception().printStackTrace();

这应该让你更容易看到之前发生的事情。否则,如果没有更多信息,似乎唯一可能的原因就是序列化。

于 2009-10-08T09:03:15.803 回答