初始化WeakReference对象以避免空检查

时间:2017-04-07 06:26:29

标签: java weak-references

鉴于以下示例代码,有一种初始化DECLARE @EmailRecipients as varchar(1000) DECLARE @MailProfileName as varchar(255) DECLARE @Msg as varchar(1000) DECLARE @NumofFails as smallint DECLARE @JobName as varchar(1000) DECLARE @Subj as varchar(1000) DECLARE @i as smallint = 1 SELECT @EmailRecipients = email_address FROM msdb.dbo.sysoperators WHERE name = <Operator Name> SELECT TOP(1) @MailProfileName = name FROM msdb.dbo.sysmail_profile SELECT * INTO #Errs FROM (SELECT rank() over (PARTITION BY step_id ORDER BY step_id) rn, ROW_NUMBER() over (partition by step_id order by run_date desc, run_time desc) ReverseTryOrder, j.name job_name, run_status, step_id, step_name, [message] FROM msdb.dbo.sysjobhistory h JOIN msdb.dbo.sysjobs j ON j.job_id = h.job_id WHERE instance_id > COALESCE((SELECT MAX(instance_id) FROM msdb.dbo.sysjobhistory WHERE job_id = $(ESCAPE_SQUOTE(JOBID)) AND step_id = 0), 0) AND h.job_id = $(ESCAPE_SQUOTE(JOBID)) ) AS agg WHERE ReverseTryOrder = 1 ---Pick the last retry attempt of each step AND run_status <> 1 -- show only those that didn't succeed SET @NumofFails = ISNULL(@@ROWCOUNT,0)---Stored here because we'll still need the rowcount after it's reset. IF @NumofFails <> 0 BEGIN DECLARE @PluralS as char(1) = CASE WHEN @NumofFails > 1 THEN 's' ELSE '' END SELECT top 1 @Subj = job_name + ':'+ CAST(@NumofFails as varchar(3)) + '''Check Steps'' Report', @Msg = '''Check Steps'' has reported that one or more Steps failed during execution of ' + job_name + CHAR(13) + CHAR(10)+ CHAR(13) + CHAR(10) FROM dbo.#Errs WHILE @i <= @NumofFails BEGIN SELECT @Msg = @Msg + 'Step ' + CAST(step_id as varchar(3)) + ': ' + step_name +CHAR(13) + CHAR(10) + [message] +CHAR(13) + CHAR(10)+CHAR(13) + CHAR(10) FROM dbo.#Errs WHERE rn = @i SET @i = @i + 1 END EXEC msdb.dbo.sp_send_dbmail @recipients = @EmailRecipients, @subject = @Subj, @profile_name = @MailProfileName, @body = @Msg END 的方法,以便我在以后使用它时不必进行空检查。我无法将值传递给构造函数。

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();
    }
}

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

由于

修改

感谢所有反馈。

  • 浮动的使用是为了简化问题,但我可以完全理解这种混淆。弱引用实际上持有的对象是Android布局中的视图,此类存在于活动生命周期之外。
  • total.get()应在评估之前分配给本地值
  • 声明“这不起作用”与:
  • 有关
使用this.total = new WeakReference<>(null); 进行初始化后,

total.get() == null评估为false 我现在明白这个陈述是不正确的。这将评估为真。但是我认为最好不要将它初始化为null并在访问之前检查null条件。

2 个答案:

答案 0 :(得分:9)

您可以像这样初始化它:

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<Float> 非常。为什么不使用原始float?或者,如果你真的想要一个Float对象。因为什么时候Float对象真的会被垃圾收集?我认为这只会导致状态不一致并难以追踪错误。

答案 1 :(得分:6)

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

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

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

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

您可以使用WeakReferencenew WeakReference< strongReferenceOfSomeObject >())对象作为方法参数来包装和传递对象。如果将其作为方法参数或Constructor参数传递给不知道上下文状态更改(可能决定对象生命周期)的类,则不应将其分配给实例变量。如果需要将其分配给实例变量,则只能将其存储为WeakReference

请参阅https://docs.oracle.com/javase/7/docs/api/java/lang/ref/WeakReference.html

P.S。对于Float,可以使用float轻松解决此问题,而不是在Float中包装WeakReference的对象。对于您所包含的相关代码,您不需要WeakReference。我上面的回答旨在提供一般WeakReference使用的高级基本承诺。