String pool


说到String类,就不得不提字符串池(String pool )。在JAVA中,String类出现的频率很高,为了提升性能,JAVA为String类特地开辟的一块内存空间,这块空间就称为字符串池。

创建String类的时候 如果是直接赋值,那么当前的String类型的值就会被添加到字符串池中。当创建第二个String类,在赋值的时候,JAVA会先在字符串池中寻找有没有已经存在的值和当前要赋进来的值一样,如果可以找到一样的,那么就将字符串池中的对应对象的引用地址返回给第二个String类。如果在字符串池中没有找到,那该值被添加到字符串池中。

示例代码:

在创建a的时候,字符串池中没有'apple'存在,所以将apple加进去。在创建b的时候,可以找的apple,就直接将apple的地址传给b。相当于虽然是两个对象,但是其实都是指向一个地址。代码运行结果是ture。

public class Try1 {

	public static void main(String[] args) {
		String a = "apple";
		String b = "apple";
		System.out.println(a==b);

	}

}

 

除了直接赋值外,还可以通过new关键字来创建一个String类的对象。每次用new创建对象的时候,JAVA还是会先在字符串池中找有没有已经存在且匹配的。如果可以找到,JAVA会堆中创建一个新的字符串,并将此字符串地址传给对象;如果没有找到,那就先将字符串添加到字符串池中,然后再在堆中创建一个该字符串,并将此字符串地址传给对象。写到这里我有点纳闷,既然你不论字符池中有没有对应字符串,都要在堆中新建一个,并且传给对象的是堆中的地址,那字符串池对你就没意义了啊。难道是为通过直接赋值的String类的对象着想?虽然没用但是创建了,所以直接赋值的String类对象可以直接拿来用?暂且先这样理解吧。

示例代码:

通过new创建出的两个String对象的地址分别对应着堆中的地址,所以不相等,结果为false。

public class Try1 {

	public static void main(String[] args) {
		String a = new String("apple");
		String b = new String("apple");
		System.out.println(a==b);
		
	}

}

在String类中还有一个小巧却很有用的方法叫intern,intern用来寻找在字符串池中有无对应的字符串,如果有,直接返回字符串;如果没有,在字符串池中加入此字符串,然后返回字符串。

示例代码:equals相等说明intern返回的是字符串,==相等说明e在被创建的时候,因为在字符池中已经存在了pear,所以直接指向,所以它和c共用同一块地址块。

public class Try1 {

	public static void main(String[] args) {	
		String c = new String("pear");
		String d = new String("pear");
		String e = "pear";
		System.out.println(c.intern().equals(d));
		System.out.println(c.intern()==e);
	}

}

在查证的过程中,发现了一篇博客胡写,他说在new一个String对象的时候不会把字符串添加到字符串池中,他的依据是new了两个相同的字符串,然后发现a.intern()==b的结果是false。这里的a调用了intern方法所以返回的是字符串池中的对象地址,而b由于是被new出来的,它所对应的是堆中的地址,肯定不相等。乍一看确实蛮有道理,不知道有多少人被他坑了hahhhh