首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Java中将字符串转换为Long的正确方法

在Java中将字符串转换为Long的正确方法
EN

Stack Overflow用户
提问于 2016-09-29 14:57:22
回答 5查看 12.3K关注 0票数 9

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

代码语言:javascript
复制
Long a = new Long(str);

代码语言:javascript
复制
Long a = Long.parseLong(str);

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

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2016-09-29 15:01:06

仔细查看返回类型:

  1. Long.parseLong(String)返回一个原语 long,因此在本例中将重新装箱:Long a = Long.parseLong(str);
  2. new Long(String)将在每种情况下创建一个新的 Long对象。所以,不要这样做,但去做3)
  3. Long.valueOf(String)返回一个Long对象,并将返回某些值的缓存实例--因此,如果您需要一个Long,这是首选变量。

在检查java.lang.Long源代码时,缓存包含以下值(SunJDK1.8):

代码语言:javascript
复制
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);
    }
}
票数 16
EN

Stack Overflow用户

发布于 2016-09-29 15:01:26

最好的方法是Long.valueOf(str),因为它依赖于Long.valueOf(long),它使用内部缓存,从而提高了效率,因为如果需要,它将重用Long-128127的缓存实例。

返回表示指定长值的Long实例。如果不需要一个新的长实例,则通常应该优先使用此方法而不是构造函数Long(long),因为该方法可能会通过缓存频繁请求的值来获得更好的空间和时间性能。注意,与Integer类中的对应方法不同,在特定范围内缓存值不需要此方法。

一般来说,使用包装类的static工厂方法valueOf(str)是一个很好的实践,比如IntegerBooleanLong、.由于大多数实例在可能的时候重用实例,因此相对于相应的parse方法或构造函数,它们在内存占用方面可能更高效。

有效Java Item 1摘录,作者:乔舒亚·布洛赫

您通常可以避免使用静态工厂方法(项目1)来创建不必要的对象,而不是在提供两者的不可变类上使用构造函数。例如,静态工厂方法Boolean.valueOf(String)几乎总是比构造函数Boolean(String)更可取。构造函数每次调用时都会创建一个新对象,而静态工厂方法从来不需要这样做,在实践中也不会这样做。

票数 9
EN

Stack Overflow用户

发布于 2016-09-29 17:04:38

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

  • 所有其他函数,即Long.valueOfLong(string)都依赖于Long.parseLong方法,该方法作为每个StringLong转换的核心方法。
  • 至于缓存,当您的输入仅在-128到127之间时(见下面的示例),这将起作用,所以要由编码器直接调用Long.parseLong,或者在对象为String类型时通过Long.valueOf调用。(显然,使用直接调用)。官方文件源代码链接 (为什么不使用Byte而不是Long,因为缓存也不会保存所有长值,即使这个范围也适用于整数)。

来自官方文档

代码语言:javascript
复制
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));
}
  • 不创建new Long对象的直接包装对象Long.valueOf 返回是一条假语句,因为根据Long.parseLong的内部用法(返回原语long),Long.parseLong的原始输出将通过创建Long类的新对象来转换为Wrapper对象,因此您希望使用直接Boxing或调用Long.valueOf=>Long.parseLong=>new Long

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

当您希望使用==进行对象类型的等式检查(如实习生字符串)时,缓存几乎没有什么帮助。Long cache只保留一个包含在-128 to 127范围内的对象的静态数组,因此如果数字超出此范围,则无法使用==运算符进行等式检查(您不相信,请尝试下面的示例)

示例:

代码语言:javascript
复制
    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);

输出:

代码语言:javascript
复制
false
false
true
true
true

因此,尝试使用equals进行等式检查。

为什么缓存需要:因为-128到127包含的数字需要给出身份,这是因为JLS (5.1.7)的性能原因,所以在这种情况下,缓存并不是为了提高时间/空间效率。

代码语言:javascript
复制
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
  • 在使用包装器类时必须使用相等的
  • 只有当您希望在-128到127之间与Wrapper类一起使用数字时,Wrapper机制的缓存才能工作。
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39773695

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档