1

我有一个长变量说,

private Long m_prevPacketRecvdTime = null;

现在我有一个 setter/getter 对,

    public void setM_prevPacketRecvdTime() {
        if (this.m_prevPacketRecvdTime == null) {
            this.m_prevPacketRecvdTime = new Long(System.currentTimeMillis());
        } else {
            // Why to create a new Object every time
                    //Why I can't just set the new value
                    //Why use new operator here instead of an Assignment or set method call
        }
    }

而不是传统的setter方法,我想改进它,1.传递long而不是Long,2.只创建一个新的Long一次,其余时间只需将新值设置为现有的Long对象。但令我难以置信的是Long中没有这样的方法。

每次我们想改变它的值时,我们真的需要创建一个新的 Long 对象吗?我们如何为现有的 Long 对象设置一个新的 long 值(与 longvalue() 正好相反)?

更多信息 在搜索答案时,我也遇到了AtomicLong,它具有类似的功能,但我不确定这是否对我有用。因为他们明确表示 AtomicLong “不能用作 Long 的替代品。

4

2 回答 2

6

你不能,这是故意的。不可变对象有很多优点——线程安全、易用性、安全性和可预测性等等。有关其他原因,请参阅 Effective Java item 15,但 Java 中的包装类都是不可变的。

也就是说,您应该使用Long.valueOf(long)(或自动装箱)而不是new Long,因为Long.valueOf知道缓存常用值。

Java 中的分配相对便宜。不要太担心它。如果您可以生成硬数字来证明切换到您自己的自定义可变包装器类型值得额外的代码复杂性,那么就这样做,但是传统的不可变包装器完全可以使用。

于 2012-05-17T06:49:34.467 回答
2

如果性能是最重要的方面,您应该考虑:

private long m_prevPacketRecvdTime = 0;

public void setM_prevPacketRecvdTime() {
    if (this.m_prevPacketRecvdTime == 0) {
        this.m_prevPacketRecvdTime = System.currentTimeMillis();
    }
}

它不仅更快而且更简单。请注意“特殊值”0,表示“未设置”。对于时间字段,我相信没关系。

另一个需要考虑的项目是使用System.currentTimeMillis(). 这是一个相对较慢的操作,甚至可能比分配新对象(使用new Long())还要慢。改进这一点有点棘手。一种选择可能是在不同的线程中使当前时间保持最新:

while (!stopped) {
    Thread.sleep(100);
    currentTime = System.currentTimeMillis();
}

然后不是System.currentTimeMillis()每次都调用,而是访问(静态)字段currentTime

于 2012-05-17T07:06:16.943 回答