30

我正在合并由两个不同的人编写的代码,并注意到将 String 值转换为 Long 有两种不同的方式。

Coder #1 已经做到了这一点:

String strId = "12345678";
...
Long lId = new Long(strId);

虽然 coder #2 已经这样做了:

String strId = "12345678";
...
Long lId = Long.valueOf(strId);

从功能上讲,代码的运行方式完全相同。每个位周围都有一个 try/catch 块来处理任何NumberFormatException抛出的问题。传入的字符串值是一个代表小数的 8 位字符串:"12345678"在这两种情况下,它都被正确转换为Long.

在构造函数中传递字符串和使用 Long.valueOf() 之间有什么功能区别吗?我在这里检查了构造函数文档:

长(java.lang.String)

和 valueOf() 的文档在这里:

Long.valueOf(java.lang.String)

据我所知,它们都调用 parseLong() 所以使用哪个并不重要。我只是想确保我不会为以后的一些奇怪行为做好准备。此外,任何一种风格都比另一种更“正确”(哈哈)吗?

4

6 回答 6

29

不同之处在于,使用new Long()你将始终创建一个新对象,而使用 时Long.valueOf(),可能会返回缓存值,long如果值介于 之间[-128 to 127]

所以,你应该更喜欢Long.valueOf方法,因为它可以为你节省一些内存。

如果您看到 的源代码Long.valueOf(String),它会在内部调用Long.valueOf(long),我在下面发布了它的源代码:-

public static Long valueOf(String s) throws NumberFormatException
{
    return Long.valueOf(parseLong(s, 10));
}

public static Long valueOf(long l) {
    final int offset = 128;
    if (l >= -128 && l <= 127) { // will cache 
        return LongCache.cache[(int)l + offset];
    }
    return new Long(l);
}
于 2012-10-30T18:23:23.923 回答
8

Long.valueOf()应该首选:它为一些常用值返回 Long 的缓存值,而不是像构造函数那样构造一个新实例。

即使某些 Java 版本不使用缓存,使用valueOf()也可以在未来的版本中使用,而构造函数将始终创建一个新实例。

于 2012-10-30T18:22:00.133 回答
3

他们的意思是一样的

public static Long valueOf(String s) throws NumberFormatException{
        return new Long(parseLong(s, 10));
}

public Long(String s) throws NumberFormatException {
    this.value = parseLong(s, 10);
}

源 JDK 6.0

于 2012-10-30T18:20:22.693 回答
3

两者都在parseLong(String, int)内部进行(int 是基数,值为 10),但valueOf具有如下所述的优势:

If a new Long instance is not required, this method should generally be used in preference to the constructor Long(long), as this method is likely to yield significantly better space and time performance by caching frequently requested values.

于 2012-10-30T18:23:16.243 回答
0

这是在 Eclipse 上运行的 PMD 插件输出

我检查的代码是

Long l = new Long("123456");

在 JDK 1.5 中,调用 new Long() 会导致内存分配。Long.valueOf() 对内存更友好。

于 2012-10-30T18:23:47.637 回答
0

我正在考虑如何为我们的应用程序更改缓存的范围和大小,并用 Longs 重载;

j2se api 不支持此类更改一种方法是使用 ClassLoader 甚至使用 JVMTI 更改加载的 java 字节码(它允许将此类技巧排除在项目之外,例如外部调整)

或者,可能是创建外部缓存和自己的静态 cachedValueOf() ,这很简单,但是取决于一些非应用程序需求的代码并不好

于 2014-04-22T10:38:26.450 回答