gpt4 book ai didi

java - 可以在完全创建对象之前调用对象方法吗?

转载 作者:搜寻专家 更新时间:2023-11-01 02:42:41 25 4
gpt4 key购买 nike

我从一位用户那里收到了一份似乎不可能的崩溃报告。堆栈跟踪表明一个对象为 null,他得到了一个 nullpointerException。

(想看的话就在这行)

public class City extends Unit {
private ArrayList<SolderType> Queue = new ArrayList<SolderType>();

public float getPrecentCompleted()
{
if(Queue.isEmpty())
{
return 0f;
}
//More code that is not relevent
}
}

解释 Queue 可能为 null 并没有遗漏太多内容,但是 Queue 仅在我的代码中的一个位置创建,即在构造函数中。所以我不明白它怎么可能为空。该对象在多个线程上共享,并且一直在创建新对象。但是Queue点只能在创建对象的时候设置。所以我不明白这怎么可能。是否有可能一个线程调用对象方法,而另一个线程创建对象但未完成?

编辑 添加了更多可能与问题相关的代码。

最佳答案

评论给出了正确答案:是的,这是可能的,除非您添加了同步来阻止它。定义两个线程之间顺序的唯一操作如下(参见 https://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.4.4):

  1. 监视器 m 上的解锁操作与所有后续锁同步对 m 的操作(其中“后续”是根据同步顺序)。
  2. 对 volatile 变量 v 的写入(§8.3.1.4)与所有同步任何线程对 v 的后续读取(其中定义了“后续”根据同步顺序)。
  3. 启动线程的操作与线程中的第一个操作同步它启动的线程。
  4. 将默认值(零、假或空)写入每个变量与每个线程中的第一个 Action 同步。虽然在分配包含变量的对象之前将默认值写入变量似乎有点奇怪,但从概念上讲,每个对象都是在程序开始时使用其默认初始化值创建的。
  5. 线程 T1 中的最终操作与线程 T1 中的任何操作同步另一个检测到 T1 已终止的线程 T2。
  6. 如果线程 T1 中断线程 T2,则由 T1 中断与任何其他线程(包括 T2)所在的任何点同步确定 T2 已被中断(通过有一个InterruptedException 抛出或通过调用 Thread.interrupted 或Thread.isInterrupted)。

如果没有这样的操作,您将看到其他线程中的对象处于未定义状态。

解决空指针异常的一种方法是使用 final 字段(参见 https://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.5 )。但是你还必须同步 ArrayList。我建议使用 java.util.concurrent 包中的队列。

关于java - 可以在完全创建对象之前调用对象方法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30142303/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com