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

时间:2019-01-24 09:19:30

标签: java string performance pool

我想更改类似

的代码
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池中操作String时,性能是否会有任何对比-基本上哪种方法更好 method-1 < / strong>或方法2

2 个答案:

答案 0 :(得分:5)

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

像这样编写它没有任何优势。

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

另外,它更冗长。

只需坚持使用方法1。

答案 1 :(得分:2)

方法2难以理解,根本没有改进。

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

它将不会从池中返回String并使用String运算符来创建new(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

     

此示例说明了六点:

     

•中的同一类(第8节(类))中的文字字符串   相同的程序包(第7节(程序包))表示对相同程序包的引用   字符串对象(第4.3.1节)。

     

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

     

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

     

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

     

•字符串由   在运行时串联是新创建的,因此是不同的。

     

•显式内联计算字符串的结果是相同的   字符串与任何具有相同内容的现有文字字符串一样。