String知识

1 new()

new关键字是新建对象,只有在new中参数是字面量时,才会去字符串常量池中寻找,并创建和引用字符串常量池中的引用,即在编译器可以确定的字符串才会发生字符串驻留现象。

2 intern()方法

由于jdk1.7中将字符串常量池改为存放在堆中,因此intern()方法的实现原理相对以前的版本也有所改变。

我们根据jdk的版本来进行一些分析:

2.1 jdk1.6中字符串常量池存放在永久代中:

当使用intern()方法时,查询字符串常量池是否存在当前字符串,若不存在则将当前字符串复制到字符串常量池中,并返回字符串常量池中的引用。

2.2 jdk1.7中字符串常量池存放在堆中:

当使用intern()方法时,先查询字符串常量池是否存在当前字符串,若字符串常量池中不存在则再从堆中查询,然后存储并返回相关引用;

若都不存在则将当前字符串复制到字符串常量池中,并返回字符串常量池中的引用。

从上面叙述中,可以得出其中的区别:

  • jdk1.6中只能查询或创建在字符串常量池;
  • jdk1.7中会先查询字符串常量池,若没有又会到堆中再去查询并存储堆的引用,然后返回。

代码校验可参考:https://tech.meituan.com/2014/03/06/in-depth-understanding-string-intern.html

3 字符串最大长度

查看源码如下

public final class String
     implements java.io.Serializable, Comparable<String>, CharSequence
 {
     /** The value is used for character storage. */
     private final char value[];
 
     /** The offset is the first index of the storage that is used. */
     private final int offset;
 
     /** The count is the number of characters in the String. */
     private final int count;    
 }

String内部是以char数组的形式存储,数组的长度是int类型,那么String允许的最大长度就是Integer.MAX_VALUE了。又由于java中的字符是以16位存储的,因此大概需要4GB的内存才能存储最大长度的字符串。不过这仅仅是对字符串变量而言,如果是字符串字面量(string literals),如“abc"、"1a2b"之类写在代码中的字符串literals,那么允许的最大长度取决于字符串在常量池中的存储大小,也就是字符串在class格式文件中的存储格式:

CONSTANT_Utf8_info {
    u1 tag;
    u2 length;
    u1 bytes[length];
}

u2是无符号的16位整数,因此理论上允许的string literal的最大长度是2^16-1=65535。然而实际测试表明,允许的最大长度仅为65534,超过就编译错误了,有兴趣可以写段代码试试,估计是length还不能为0。

public class StringTest {

 public static void main(String[] args){

  int i = 0;
  String string = "";
  while(i <65536){
   string = string + "1"; // 这样写常量池中只存在 “1” 这个字符串          string 实际在分配的堆空间中 所以string的大小可达到大概4GB
   System.out.println(string.length());
   i++;
  }
 }
}
上一篇:String的intern方法


下一篇:Oracle和MySQL数据库的备份与恢复