常量池中字符串的操作与非常量池中字符串的操作 - 性能
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.
我想更改类似于
的代码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.