为了账号安全,请及时绑定邮箱和手机立即绑定

在常量池中操作字符串与在非常量池中操作字符串 - 性能

在常量池中操作字符串与在非常量池中操作字符串 - 性能

慕森卡 2022-05-21 18:31:01
我想更改一个类似的代码if("T".equalsIgnoreCase(bo.getSubjectType()))  //method-1到if(String.valueOf('T').equalsIgnoreCase(bo.getSubjectType()))  //method-2所以出于这个原因,我写了一个示例代码String s1 = "T";String s2 = "T";char c1 = 'T';char c2 = 'T';System.out.println(String.valueOf(c1) == String.valueOf(c2));   //  falseSystem.out.println(s1 == s2);   //  true这几乎可以说String.valueOf(arg)会产生一个字符串文字并将其放在constant pool. non-constant所以我的问题是,当我们尝试在池中操作 String 和在 a 中操作 String 时,性能上是否会有任何差异constant pool——基本上哪一个会更好地接近method-1或method-2?
查看完整描述

2 回答

?
慕盖茨4494581

TA贡献1850条经验 获得超11个赞

if(String.valueOf('T').equalsIgnoreCase(bo.getSubjectType()))

像这样写它没有任何好处。

String.valueOf('T')将始终返回一个新字符串,等于"T",因为String.valueOf(char)(或任何valueOf重载,就此而言)的结果没有被缓存。没有理由一遍又一遍地创建相同的字符串。

另外,它更冗长。

只要坚持方法1。


查看完整回答
反对 回复 2022-05-21
?
LEATH

TA贡献1936条经验 获得超6个赞

方法 2 是难读的,根本没有任何改进。


String使用newoperator 运算符创建,它总是在堆内存中创建一个新对象。Stringcreated usingString literal可能会从 中返回一个现有对象String pool,如果它已经存在的话。


它不会String从池中返回 a 并创建一个Stringusingnew运算符(Oracle JDK 10 源代码):


 /**

 * Returns the string representation of the {@code char}

 * argument.

 *

 * @param   c   a {@code char}.

 * @return  a string of length {@code 1} containing

 *          as its single character the argument {@code c}.

 */

public static String valueOf(char c) {

    if (COMPACT_STRINGS && StringLatin1.canEncode(c)) {

        return new String(StringLatin1.toBytes(c), LATIN1);

    }

    return new String(StringUTF16.toBytes(c), UTF16);

}

如果你想定义一个String常量并且总是从池中加载,只需创建一个:


public static final String T = "T";

关于JLS字符串文字和池:


class Test {

   public static void main(String[] args) {

   String hello = "Hello", lo = "lo";

   System.out.print((hello == "Hello") + " ");

   System.out.print((Other.hello == hello) + " ");

   System.out.print((other.Other.hello == hello) + " ");

   System.out.print((hello == ("Hel"+"lo")) + " ");

   System.out.print((hello == ("Hel"+lo)) + " ");

   System.out.println(hello == ("Hel"+lo).intern());

 }

}

class Other { static String hello = "Hello"; }

和编译单元:


package other; 

public class Other { 

    public static String hello = "Hello"; 

}

产生输出:


true true true true false true


这个例子说明了六点:


• 同一包 (§7 (Packages)) 中的同一类 (§8 (Classes)) 中的文字字符串表示对同一 String 对象 (§4.3.1) 的引用。


• 同一包中不同类中的文字字符串表示对同一字符串对象的引用。


• 不同包中不同类中的文字字符串同样表示对同一字符串对象的引用。


• 由常量表达式(第 15.28 节)计算的字符串在编译时计算,然后将其视为文字。


• 在运行时通过连接计算的字符串是新创建的,因此是不同的。


• 显式内嵌计算字符串的结果是与任何具有相同内容的预先存在的文字字符串相同的字符串。


查看完整回答
反对 回复 2022-05-21
  • 2 回答
  • 0 关注
  • 103 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信