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

Manipulation of a string in constant pool vs Manipulation of a string in non-constant pool - Perfomance

我想更改类似于

的代码
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));   //  false
System.out.println(s1 == s2);   //  true

这几乎就是说 String.valueOf(arg) 生成一个字符串文字并将其放在 constant pool 中。所以我的问题是,当我们尝试在 non-constant 池中和在 constant pool 中操作字符串时,性能是否会有任何差异 - 基本上哪个方法更好 方法 - 1 方法 2?

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

这样写也没什么好处

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

另外,它更冗长。

坚持使用方法 1。

方法 2 难以阅读,根本没有改进。

String created using new operator 运算符,它总是在堆内存中创建一个新对象。 String 使用 String literal 创建可能 return 来自 String pool 的现有对象,如果它已经存在的话。

它不会从池中 return String 并使用 new 运算符创建 String (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"; }

and the compilation unit:

package other; 
public class Other { 
    public static String hello = "Hello"; 
}

produces the output:

true true true true false true

This example illustrates six points:

• Literal strings within the same class (§8 (Classes)) in the same package (§7 (Packages)) represent references to the same String object (§4.3.1).

• Literal strings within different classes in the same package represent references to the same String object.

• Literal strings within different classes in different packages likewise represent references to the same String object.

• Strings computed by constant expressions (§15.28) are computed at compile time and then treated as if they were literals.

• Strings computed by concatenation at run time are newly created and therefore distinct.

• The result of explicitly interning a computed string is the same string as any pre-existing literal string with the same contents.