在 Java 中将 String 转换为 Long 的正确方法

Correct way of converting String to Long in Java

String 转换为 Long(对象)的最佳方式是什么Java.

Long a = new Long(str);

Long a = Long.parseLong(str);

这里有没有正确的方法,因为两者似乎具有相同的可读性水平,并且在第一种方法中添加额外的步骤 autoboxing 是否可以接受?

来自源代码:

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

如果你不相信:

来自 Javadoc:

Constructs a newly allocated Long object that represents the long value indicated by the String parameter. The string is converted to a long value in exactly the manner used by the parseLong method for radix 10.

仔细查看 return 类型:

  1. Long.parseLong(String) return是一个primitive long,所以会出现这种情况的重装箱:Long a = Long.parseLong(str);
  2. new Long(String) 将在每种情况下创建一个 new Long 对象。所以,不要这样做,而是选择 3)
  3. Long.valueOf(String) return 是一个 Long 对象,并且会 return 为某些值缓存实例——所以如果你需要一个 Long 这是首选变体。

检查 java.lang.Long 源,缓存包含以下值(Sun JDK 1.8):

private static class LongCache {
    private LongCache(){}

    static final Long cache[] = new Long[-(-128) + 127 + 1];

    static {
        for(int i = 0; i < cache.length; i++)
            cache[i] = new Long(i - 128);
    }
}

最好的方法是 Long.valueOf(str),因为它依赖于 Long.valueOf(long),它使用内部缓存使其更高效,因为如果需要,它将重用来自 Long 的缓存实例=13=] 到 127 包括在内。

Returns a Long instance representing the specified long value. 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. Note that unlike the corresponding method in the Integer class, this method is not required to cache values within a particular range.

一般来说,使用包装器 class 的 static 工厂方法 valueOf(str) 是一个很好的做法,例如 IntegerBooleanLong, ... 因为它们中的大多数只要有可能就会重用实例,从而使它们在内存占用方面比相应的 parse 方法或构造函数更有效。


摘自 Effective Java Item 1 作者 Joshua Bloch:

You can often avoid creating unnecessary objects by using static factory methods (Item 1) in preference to constructors on immutable classes that provide both. For example, the static factory method Boolean.valueOf(String) is almost always preferable to the constructor Boolean(String). The constructor creates a new object each time it’s called, while the static factory method is never required to do so and won’t in practice.

我想建议使用 Long.parseLong 而不是所有其他选项,因为 :

  • 每个其他函数,即 Long.valueOfLong(string) 依赖于 Long.parseLong 方法,它作为每个 StringLong 转换的核心方法。
  • 关于缓存,当您的输入仅在 -128 到 127 之间时,这将起作用(请参见下面的示例),因此这取决于您要调用的编码器 Long.parseLong 直接或通过 Long.valueOf 当你的对象是 String 类型时。(显然,使用直接调用)。official docs and the source code link (为什么不使用 Byte 而不是 Long 因为缓存即使此范围也适用于整数,也不会保存每个长值)

来自官方文档

public static Long valueOf(String s)
                    throws NumberFormatException
Returns a Long object holding the value of the specified String. The argument is interpreted as representing a signed decimal long, exactly as if the argument were given to the parseLong(java.lang.String) method. The result is a Long object that represents the integer value specified by the string.
**In other words, this method returns a Long object equal to the value of:**

new Long(Long.parseLong(s))

// internally calls to Long.valueOf when you pass string

public static Long valueOf(String s) throws NumberFormatException
{
    return Long.valueOf(parseLong(s, 10));
}
  • 关于Long.valueOf返回直接Wrapper对象而不创建new Long对象是一个错误的陈述,因为根据 Long.parseLong 的内部使用(其中 returns 一个原始 long),Long.parseLong 的原始输出将通过创建 [=19 的新对象来转换为 Wrapper 对象=] class 因此你想直接使用 Boxing 或者可以调用 Long.valueOf=>Long.parseLong=>new Long

关于缓存的更多信息(如果传递值很长):

当您想使用 == 对对象类型进行相等性检查(如 intern 字符串)时,缓存几乎没有帮助。长缓存只会保留一个静态对象数组,其值在 -128 to 127 范围内(含),因此如果您的数字超出此范围,则您将无法使用 == 运算符用于相等检查(你不相信,试试下面的例子)

示例:

    Long b2=128L;
    Long b3=128L;
    Long aa=Long.valueOf("134");
    Long ab=Long.valueOf("134");
    System.out.println(b2==b3); // no cache for out of range values
    System.out.println(aa==ab);  // no cache for out of range values
    System.out.println(aa.equals(ab)); // must use equals for equality check
    System.out.println(b2.equals(b3));
    b2=44; // between -128 to 127 it will work
    b3=44;
    System.out.println(b2==b3);

输出:

false
false
true
true
true

所以尝试使用equals进行相等性检查。

为什么需要缓存:因为 -128 到 127 之间的数字需要为 JLS (5.1.7) 的性能原因提供标识] 所以在这种情况下缓存不是为了 time/space 效率。

public static Long valueOf(long l) {
    final int offset = 128;
    if (l >= -128 && l <= 127) { // will cache , range is clearly seen 
        return LongCache.cache[(int)l + offset];
    }
    return new Long(l);
}

结论:

  • 使用Long.parseLong.
  • 在使用 Wrapper classes.
  • 时必须使用 equals
  • java 机制的缓存仅在您想要使用 -128 到 127Wrapper classes 之间的数字时才起作用。