1、String对象的比较
String 是一个常量,从String类中的代码可以看出。String类内部是通过char数组来存储字符串,这个char数组是被声明成final的。
1 // Java中只要使用了new 则生成一个新的对象,该对象永远在堆中,stringpool初始化为空,是由string类单独维护的 2 // 首先在stringpool中找abc对象,若没有则在stringpool创建abc对象,之后在堆中生成一个abc对象,即生成两个对象 3 String s = new String("abc");// s指向的是堆中的对象 4 // 首先从stringpool中去查找是否有abc对象,若有,则不生成(若没有则在stringpool生成abc对象,在用s1指向abc对象)。再用s1指向stringpool中的abc对象 5 String s1 = "abc"; 6 // 首先在stringpool中找abc对象,若有,则不创建。之后在堆中生成一个abc对象,并把s2指向堆中的对象 7 String s2 = new String("abc"); 8 9 System.out.println(s == s1); 10 System.out.println(s == s2); 11 System.out.println(s1 == s2);
代码执行内存中的变化如下:
代码执行完第3行的时候,此时会在stringpool中生成了一个abc对象,接着在堆中生成一个abc对象,并把堆中生成的abc对象的引用返回给s。
代码执行完第5行的时候,因为此时stringpool中已经有了一个abc对象,所以不会继续在stringpool中创建abc对象,s1就直接指向了stringpool中这个abc对象。
代码执行完第5行的时候,因为此时stringpool中已经有了一个abc对象,所以不会继续在stringpool中创建abc对象。而是在堆中生成一个abc对象,并把s2指向它。
对于引用类型来说,== 判断的是地址,对于原始数据类型来说==比较的是字面值,所以执行输出的结果如下:
false
false
false
内存示意图如下:
2、String对象的intern()方法
intern()的含义(返回的都是stringpool中的对象)若stringpool中包含abc,则返回stringpool中的abc对象的地址。若stringpool中不存在abc对象,则在stringpool中创建abc对象,并且把stringpool中abc对象的地址返回。
1 String s = new String("abc"); 2 String s1 = "abc"; 3 String s2 = new String("abc"); 4 5 System.out.println(s == s.intern()); 6 System.out.println(s1 == s1.intern()); 7 System.out.println(s.intern() == s2.intern());
第5行代码执行的时候,此时stringpool已经有了一个abc对象,s.intern()会将stringpool中的abc对象返回,而s指向的是堆中的abc对象,故为假。
第6行代码执行的时候,此时stringpool已经有了一个abc对象,1s.intern()会将stringpool中的abc对象返回,而s1指向的也是在stringpool中的abc对象,故为真。
第7行代码执行的时候,此时stringpool已经有了一个abc对象,s1.intern()和s2.intern()都是将stringpool中的abc对象返回,故为真。
执行的结果如下
false
true
true
3、关于String中“+”操作
a、当 + 两边都是字面值(常量值)的时候,执行完+后,会首先判断stringpool值是否存在hello对象,若有则返回stringpool中的hello对象的地址。(若没有则创建,并返回stringpool中的对象)
b、当 + 操作时,若+两边有一个不是字面值的常量的时候,(不会检查stringpool,)java会直接在堆中生成一个hello对象,并把堆中的hello对象返回
1 String hello = "hello"; 2 String hel = "hel"; 3 String lo = "lo"; 4 5 System.out.println(hello == "hel" + "lo");//编译后的代码为System.out.println(hello == "hello"); 6 System.out.println(hello == "hel" + lo);//编译后的代码为System.out.println(hello == (new StringBuilder("hel")).append(lo).toString());
第5行代码执行的时候,此时stringpool已经有了一个hello对象,"hel" + "lo"也是将stringpool中的hello对象返回,故为真。
第6行代码执行的时候,"hel" + lo因为lo不是一个常量,所以"hel" + lo ,java会在堆中生成一个hello对象并返回。所以这个两个对象一个在stringpool中,一个在堆中,故为假。
执行结果如下:
true
false
4、关于String中concat(String str)方法
concat方法主要是将两个字符串连接起来,当传入的参数长度为0的时候,返回调用对象的本身;否则就对两个字符串进行拼接,生成一个新的对象返回。
1 String hello = "hello"; 2 String hel = "hel"; 3 String lo = "lo"; 4 5 System.out.println(hello == hel.concat(lo));
执行结果如下:
false
通过查看String类中concat(String str)方法可以得知结果,源码如下:
1 public String concat(String str) { 2 int otherLen = str.length(); 3 if (otherLen == 0) { 4 return this; 5 } 6 int len = value.length; 7 char buf[] = Arrays.copyOf(value, len + otherLen); 8 str.getChars(buf, len); 9 return new String(buf, true); 10 }
第3行判断传入的参数长度是否为0,如果为0就将调用对象返回;如果不为0就进行拼接,最后以new的方式在堆中创建一个新的String对象,并返回。所以当参数长度不为0的时候使用concat方法返回的对象总是在堆中新创建的对象。故进行对象比较为false。