【问题标题】:Initialise WeakReference object to avoid null check初始化 WeakReference 对象以避免空值检查
【发布时间】:2017-04-07 06:26:29
【问题描述】:

鉴于下面的示例代码,有没有一种方法可以初始化 total,这样我以后使用它时就不必进行空值检查。我无法将值传递给构造函数。

public class SampleCode 
{

    private WeakReference<Float> total;

    public SampleCode() {
    }

    public void setWidget(Float total) {
        this.total = new WeakReference<>(total);
    }

    public float calculatePercentage(Float count) {
        if (total == null) {
            return -1;
        }
        if (total.get() == null) {
            return -1;
        }

        return count / total.get();
    }
}

我想在构造函数中做这样的事情:

this.total = new WeakReference<>(null);

但这不起作用。我可以在发布状态下初始化 WeakReference 还是违背了类的目的?

谢谢

编辑

感谢所有反馈。

  • 使用浮点数是为了简化问题,但我完全可以理解其中的困惑。弱引用实际持有的对象是 Android 布局中的视图,并且此类存在于活动生命周期之外。
  • total.get() 应在计算之前分配给本地值
  • “这不起作用”的声明涉及:

total.get() == null 在使用 this.total = new WeakReference&lt;&gt;(null); 初始化后评估为 false 我现在明白这种说法是不正确的。这将评估为真。但是我认为最好不要将其初始化为 null 并在访问之前检查 null 条件。

【问题讨论】:

  • 你在ctor中初始化它不起作用是什么意思?
  • 您似乎在这里提出了不止一个问题。一个是关于避免 null 检查,另一个是关于在 null/released 状态下初始化。
  • 为什么?为什么使用WeakReference?为什么使用Float?为什么不是float
  • @running-codebase 正如 EJP 在 cmets 中所说,您包含的代码不需要 WeakReference,只需使用原始浮点数即可。但是您仍然参考我对 WeakReference 的一般用法的回答 stackoverflow.com/a/43271770/504133
  • @nits.kk 为了清晰起见,我添加了一些编辑。 Float 的使用旨在简化代码,以专注于如何正确地使用空值初始化 WeakReference。我能理解我造成的混乱。感谢您的反馈。

标签: java weak-references


【解决方案1】:

你可以这样初始化它:

private WeakReference<Float> total = new WeakReference<>(null);

现在引用本身永远不会为 null,但它的 get 方法确实返回 null。
新的 calculatePercentage 方法示例:

public float calculatePercentage(Float count) {
    Float totalF = total.get();
    if(totalF == null)
        return -1;

    return count / totalF;
}

但是
在大多数情况下,使用WeakReference&lt;Float&gt; 没有什么意义非常。为什么不直接使用原语float?或者,如果您真的想要 Float 对象。因为 Float 对象何时真正被垃圾回收?我认为这只会导致不一致的状态和难以跟踪的错误。

【讨论】:

  • 实际对象将被包裹在 WeakReference 的什么位置。我只看到new WeakReference&lt;&gt;(null);
  • @nits.kk 它将通过为total 分配一个新的 WeakReference 来设置。在这个问题中,这是在他的setWidget(Float total) 方法中完成的。
【解决方案2】:

使用WeakReference 时,您必须始终在使用前检查是否为空。假设有一个对象A,它的存在取决于其他一些上下文状态。

如果这样的对象被传递给某个不知道那些上下文状态的类,那么传递包裹在WeakReference 对象中的对象总是更好。随着对此类对象的强引用数变为 0,在执行下一个垃圾收集器周期时,该对象将被垃圾收集。此时WeakReference 的对象将在调用get() 时开始给出null。这是一个信号给使用类(它不知道上下文状态)对象的生命周期已经结束。

在使用它之前最好的方法是将对象存储在局部变量中(在调用get()之后),检查空检查然后使用它。

即使您根据weakReference.get() 的条件检查了 not null 并不意味着它不能为下一行。您需要将get() 返回的对象存储在局部变量中,检查它是否为非空,然后使用。 记住不要将对象(由get() 返回)存储为实例变量,因为它会创建对该对象的强引用。 只需创建局部变量,不要将这些局部变量传递给其他方法。只需在那里使用它们,让它们随着作用域的结束而死亡。

您可以使用 WeakReference ( new WeakReference&lt; strongReferenceOfSomeObject &gt;() ) 的对象作为方法参数来包装和传递对象。如果您将其作为方法参数或构造函数参数传递给不知道上下文状态更改(可能决定对象寿命)的类,则不应将其分配给实例变量。如果需要将其分配给实例变量,则只能将其存储为WeakReference

更多信息请访问https://docs.oracle.com/javase/7/docs/api/java/lang/ref/WeakReference.html

P.S. 对于Float,这可以使用float 轻松解决,而不是将Float 的对象包装在WeakReference 中。对于您所包含的代码,您不需要WeakReference。我上面的回答旨在提供对WeakReference 用法的高级基本理解。

【讨论】:

  • 如果total 可以在对calculatePercentage() 的调用之间发生变化,则OP 的代码可能需要WeakReference。然后calculatePercentage 方法将始终使用total 的当前值。 (但在那种情况下,我认为 WeakReference 不适合使用;也许只是一个简单的参考。)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-09
相关资源
最近更新 更多