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

时间:2016-09-29 14:57:22

标签: java autoboxing

在Java中将 String 转换为 Long (对象)的首选方法是什么。

Long a = new Long(str);

OR

Long a = Long.parseLong(str);

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

5 个答案:

答案 0 :(得分:15)

仔细查看返回类型:

  1. Long.parseLong(String)会返回原语 long,因此在这种情况下会重新装箱:Long a = Long.parseLong(str);
  2. new Long(String)会在每种情况下创建 Long对象。所以,不要这样做,而是去3)
  3. Long.valueOf(String)会返回Long个对象,并会返回某些值的缓存实例 - 因此,如果您需要Long,则这是首选变体。
  4. 检查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);
        }
    }
    

答案 1 :(得分:8)

最好的方法是Long.valueOf(str),因为它依赖于Long.valueOf(long),它使用内部缓存使其更有效,因为如果需要,Long的缓存实例将从{{1}重用包含-128的内容。

  

返回表示指定long值的127实例。如果一个   新的Long实例不是必需的,这个方法一般应该是   优先使用构造函数Long,因为这个方法是   可能会产生明显更好的空间和时间表现   缓存频繁请求的值。注意,不像   在Integer类中对应的方法,不需要此方法   缓存特定范围内的值。

一般来说,最好使用Long(long)staticvalueOf(str)等包装类的Integer工厂方法Boolean。 ..因为只要有可能使它们在内存占用方面比相应的Long方法或构造函数更有效,它们中的大多数都会重用实例。

Joshua Bloch撰写的Effective Java parse摘录

  

您通常可以使用 static来避免创建不必要的对象   工厂方法(第1项)优先于不可变的构造函数   提供两者的类。例如,静态工厂方法   Item 1几乎总是优先于   构造函数Boolean.valueOf(String)。构造函数创建一个新对象   每次调用它时,静态工厂方法永远不会   要求这样做,而不是在实践中。

答案 2 :(得分:2)

我建议使用Long.parseLong覆盖所有其他选项,因为:

  • 其他所有功能,即Long.valueOfLong(string)都依赖于Long.parseLong方法,该方法可作为每次StringLong转换的核心方法。
  • 关于缓存,当您的输入仅在 -128到127 之间时,这将起作用(请参阅下面的示例),因此您需要直接调用Long.parseLong的编码器当您的对象属于Long.valueOf类型时,或者通过String。(显然,使用直接调用)。official docssource 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 对象是一个错误的声明,根据内部使用的{{1 (返回一个基元long),Long.parseLong的基本输出将通过创建Long.parseLong类的新对象转换为Wrapper对象,因此你想使用直接Long或者可以致电Boxing

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

如果要使用 == 进行具有对象类型的相等性检查(如实习字符串),则缓存很有用。长缓存只会保留一个静态数组的对象,其值在 Long.valueOf=>Long.parseLong=>new Long 范围内,所以如果您的数字超出此范围,那么您将无法使用 == 运算符用于等式检查(您不相信,请尝试以下示例)

示例:

-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 进行相等检查。

为什么需要缓存:因为JLS (5.1.7)的性能原因需要为 -128到127 之间的数字提供身份,因此缓存不适用于时间/在这种情况下的空间效率。

equals

结论:

  • 使用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); }
  • 使用 Wrapper 类时,
  • 必须使用等于
  • 只有在 -128到127 Long.parseLong类之间使用数字时,才能使用缓存for java机制。

答案 3 :(得分:1)

来自源代码:

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

万一你不相信: enter image description here

答案 4 :(得分:0)

来自Javadoc:

  

构造一个新分配的Long对象,表示long   String参数指示的值。该字符串将转换为a   完全按照parseLong方法使用的方式的long值   基数10。