什么是字符串常量池?

在理解字符串常量前,我们先熟悉一下如何创建一个字符串,在Java中有两种方法可以创建一个字符串对象:

  • 使用new运算符。例如:
    String str = new String("Hello");
     
  • 使用字符串常量或者常量表达式。例如:
    String str="Hello"; //(字符串常量) 或者
        String str="Hel" + "lo"; //(字符串常量表达式).
     这些字符串的创建方式之间有什么区别呢?在Java中,equals方法被认为是对象的值进行深层次的比较,而操作符==是进行的浅层次的比较。equals方法比较两个对象的内容而不是引用。==两侧是引用类型(例如对象)时,如果引用是相同的-即指向同一个对象-则执行结果为真。如果是值类型(例如原生类型),如果值相同,则执行结果为真。equals方法在两个对象具有相同内容时返回真-但是,java.lang.Object类中的equals方法返回真-如果类没有覆盖默认的equals方法,如果两个引用指向同一个对象。

    让我们通过下面的例子来看看这两种字符串的创建方式之间有什么区别吧。

    public class DemoStringCreation {
        public static void main(String args[]) {
          String str1 = "Hello";
          String str2 = "Hello";
          System.out.println("str1 and str2 are created by using string literal.");
          System.out.println("	str1 == str2 is " + (str1 == str2));
          System.out.println("	str1.equals(str2) is " + str1.equals(str2));  
          String str3 = new String("Hello");
          String str4 = new String("Hello");
          System.out.println("str3 and str4 are created by using new operator.");
          System.out.println("	str3 == str4 is " + (str3 == str4));
          System.out.println("	str3.equals(str4) is " + str3.equals(str4));  
          String str5 = "Hel" + "lo";
          String str6 = "He" + "llo";
          System.out.println("str5 and str6 are created by using string constant expression.");
          System.out.println("	str5 == str6 is " + (str5 == str6));
          System.out.println("	str5.equals(str6) is " + str5.equals(str6));  
          String s = "lo";
          String str7 = "Hel" + s;
          String str8 = "He" + "llo";
          System.out.println("str7 is computed at runtime.");
          System.out.println("str8 is created by using string constant expression.");
          System.out.println("	str7 == str8 is " + (str7 == str8));
          System.out.println("	str7.equals(str8) is " + str7.equals(str8));  
        }
      }

     输出:

    str1 and str2 are created by using string literal.
      str1 == str2 is true
      str1.equals(str2) is true
    str3 and str4 are created by using new operator.
      str3 == str4 is false
      str3.equals(str4) is true
    str5 and str6 are created by using string constant expression.
      str5 == str6 is true
      str5.equals(str6) is true
    str7 is computed at runtime.
    str8 is created by using string constant expression.
      str7 == str8 is false
      str7.equals(str8) is true

     使用相同的字符序列而不是使用new关键字创建的两个字符串会创建指向Java字符串常量池中的同一个字符串的指针。字符串常量池是Java节约资源的一种方式。

    字符串常量池

    字符串的分配,和其他的对象分配一样,耗费高昂的时间与空间代价。JVM为了提高性能和减少内存开销,在实例化字符串常量的时候进行了一些优化。为了减少在JVM中创建的字符串的数量,字符串类维护了一个字符串池,每当代码创建字符串常量时,JVM会首先检查字符串常量池。如果字符串已经存在池中,就返回池中的实例引用。如果字符串不在池中,就会实例化一个字符串并放到池中。Java能够进行这样的优化是因为字符串是不可变的,可以不用担心数据冲突进行共享。例如:

    public class Program
      {
        public static void main(String[] args)
        {
           String str1 = "Hello";  
           String str2 = "Hello"; 
           System.out.print(str1 == str2);
        }
      }

     其结果是:true

  • Java语言规范第三版中的字符串常量

    每一个字符串常量都是指向一个字符串类实例的引用。字符串对象有一个固定值。字符串常量,或者一般的说,常量表达式中的字符串都被使用方法 String.intern进行保留来共享唯一的实例。

  • package testPackage;
        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 { static String hello = "Hello"; }
     产生输出:
    true true true true false true
     
    这个例子说明了六点:
    
    同一个包下同一个类中的字符串常量的引用指向同一个字符串对象;
    同一个包下不同的类中的字符串常量的引用指向同一个字符串对象;
    不同的包下不同的类中的字符串常量的引用仍然指向同一个字符串对象;
    由常量表达式计算出的字符串在编译时进行计算,然后被当作常量;
    在运行时通过连接计算出的字符串是新创建的,因此是不同的;
    通过计算生成的字符串显示调用intern方法后产生的结果与原来存在的同样内容的字符串常量是一样的。
     
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值