首页 > 解决方案 > Java VM 不能与 `android.util.*` 一起使用:可变类不能用非零值初始化

问题描述

我正在使用具有 API 级别 26 和最小 API 21 的 Android Studio 3.1.2。我检查并看到该包android.util的类型MutableDouble具有如下实现:

package android.util;

/**
 */
public final class MutableInt {
  public int value;

  public MutableInt(int value) {
    this.value = value;
  }
}

但是当我用特定的输入值初始化新实例时MutableDouble,它总是收到这样的零值:

MutableDouble d = new MutableDouble(999d);
System.out.println("Received value: " + d.value);
=> "Received value: 0.0"

我必须直接设置值才能使其工作

MutableDouble d = new MutableDouble(999d);
d.value = 777d;
System.out.println("Received value: " + d.value);
=> "Received value: 777.0"

我已将上述实现复制MutableDouble到我自己的项目中,并且按预期工作。

检查其他类似的类,如MutableInt,MutableFloat等,它们有同样的问题。

有没有人和我一样遇到过这个问题?Android Studio 中的任何错误配置会导致此问题吗?

标签: javaandroid

解决方案


我相信这些功能已被弃用,因此在使用 Android Studio >= 3.1.0 (Android P SDKs) 时将无法正常工作。我不知道他们为什么不推荐使用 MutableInt、MutableDouble、... 类,但我认为这是因为通过引用传递文字对于异步应用程序来说非常危险,而且它们真的很容易实现!我建议像这样使用 AtomicLong:

AtomicLong d = new AtomicLong(Double.doubleToLongBits(99.9));
System.out.println("Double is set to " + Double.longBitsToDouble(d.longValue()));

通过引用传递 会更安全。

如果您可以引入 Guava 包,还可以使用Guava AtomicDouble 类。

另一个想法是使用 AtomicLong 创建一个您自己的简单 AtomicDouble 类,如下所示:

import java.util.concurrent.atomic.AtomicInteger;
import static java.lang.Double.*;

class AtomicDouble extends Number {

    private AtomicLong bits;

    public AtomicDouble() {
        this(0.0);
    }

    public AtomicDouble(double initialValue) {
        bits = new AtomicInteger(doubleToLongBits(initialValue));
    }

    public final boolean compareAndSet(double expect, double update) {
        return bits.compareAndSet(doubleToLongBits(expect),
                                  doubleToLongBits(update));
    }

    public final void set(double newValue) {
        bits.set(doubleToLongBits(newValue));
    }

    public final double get() {
        return longBitsToDouble(bits.get());
    }

    public double doubleValue() {
        return get();
    }

    public final float getAndSet(double newValue) {
        return longBitsToDouble(bits.getAndSet(doubleToLongBits(newValue)));
    }

    public final boolean weakCompareAndSet(double expect, double update) {
        return bits.weakCompareAndSet(doubleToLongBits(expect),
                                      doubleToLongBits(update));
    }

    public float floatValue() { return (float) doubleValue(); }
    public int intValue()       { return (int) get(); }
    public long longValue()     { return (long) get(); }

}

推荐阅读