鉴于以下示例代码,有一种初始化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,还是违反了类的目的?
由于
修改
感谢所有反馈。
this.total = new WeakReference<>(null);
进行初始化后, total.get() == null
评估为false
我现在明白这个陈述是不正确的。这将评估为真。但是我认为最好不要将它初始化为null并在访问之前检查null条件。
答案 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()
返回)存储为实例变量,因为它会创建对象的强引用。只需创建局部变量,不要将这些局部变量传递给其他变量方法。只要在那里使用它们,让它们在范围结束时死亡。
您可以使用WeakReference
(new 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
使用的高级基本承诺。