【问题标题】:Are Longs in java too harsh ? Why so?java中的Longs是否过于苛刻?为什么这样?
【发布时间】:2012-05-17 06:47:07
【问题描述】:

我有一个 Long 变量说,

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 的替代品。

【问题讨论】:

    标签: java wrapper long-integer


    【解决方案1】:

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

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

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

    【讨论】:

    • +1,对于这么好的答案,我真的很期待这个答案.. 但是我仍然不相信每次我需要创建一个新对象时,有没有更好的方式 ? Long.valueOf(long) 很好,但最终也会返回一个新对象...谢谢
    • 创建一个新的 Long 非常、非常、非常快。不要预先优化。
    • 不要再认为对象很昂贵。他们真的不是。但唯一的选择是创建你自己的 MutableLong 类来包装 long
    【解决方案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

    【讨论】:

    • +1 您也可以使用未设置的Long.MIN_VALUE。我还使用Long.MAX_VALUE 来处理“未设置”的超时。
    • @anDroider 为什么你需要java.lang.Long?您可以随时根据需要将long 转换为java.lang.Long
    • 这个变量被多个线程使用......所以每次访问它之前我都会使用 synchronized(){} 锁定这个变量,相同的功能不能长时间使用,只有其他选项是同步getter/setters...我现在将尝试第二种方法(长期同步 getter/setter),因此无需 Long...
    • 在 java.lang.Long 上同步没有意义。同步的 getter 和 setter 可能有意义,但AtomicLong 会更快,因为这将消除同步的需要(请参阅AtomicLong 的文档)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-15
    • 2010-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多