【问题标题】:final boolean [] vs final boolean inside Runnable最终布尔值 [] 与 Runnable 中的最终布尔值
【发布时间】:2017-03-01 00:33:02
【问题描述】:

为什么允许以下行为:

final boolean [] success = new boolean[1];
    Thread httpThread = new Thread(new Runnable() {
        @Override
        public void run() {
            HTTPConnect httpConnect = new HTTPConnect(getContext());
            success[0] = false
            ...
            if (whatever)
            success[0] = true;

但以下不是?

final boolean success;
    Thread httpThread = new Thread(new Runnable() {
        @Override
        public void run() {
            HTTPConnect httpConnect = new HTTPConnect(getContext());
            success = false
            ...
            if (whatever)
            success = true;

我在这里指的是boolean success。 起初我以为这是因为本地声明会失去作用域,而堆上的声明会在作用域结束后继续存在,但这似乎并非如此,因为像 final ArrayList<Foo> bar = new ArrayList<>() 这样的声明不能被赋值。

【问题讨论】:

  • 从代码中删除所有不必要的部分,你问为什么这不起作用:boolean success; success[0] = true; 答案很简单:因为success 是原始布尔值而不是数组。
  • @Kiryl 这是一个错字,已修复。

标签: java multithreading runnable


【解决方案1】:

因为您实际上将 boolean 值包装在一个数组中,以便您可以更改数组的内容,但您不会更改变量 success 本身的引用。

使用AtomicBoolean(或一般AtomicReference)可以获得相同的结果。

匿名内部类修改变量的问题出现在以下场景

boolean success;
Thread httpThread = new Thread(new Runnable() {
  @Override
  public void run() {
    success = false;
    ....

这是不允许的,因为您正在更改success 所指的内容。如果您使用boolean[],那么您不会更改success 所指的内容,而是包含在所指对象中的值,因此没有问题。

【讨论】:

    【解决方案2】:

    首先,您的第二个示例有几个拼写错误:由于 successboolean,因此赋值语句不应下标。

    我假设在这两种情况下,success 都是一个局部变量。如果它是一个字段,那么您可以简单地消除final 并且第二种情况将起作用(消除下标之后)。

    第二种方法不适用于局部变量的原因是您无法在分配final 变量后对其进行分配。数组的情况有点不同:您仍然无法将新数组分配给success,但您可以为数组的元素分配新值。这就是第一种方法有效的原因。使用这样的数组是处理这个问题和 Java 方法没有“out”参数的问题的常见习惯用法。

    【讨论】:

      猜你喜欢
      • 2018-02-09
      • 1970-01-01
      • 2011-04-13
      • 2017-04-08
      • 2014-09-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多