1. String对象是不可变的,String类中每一个看起来修改String值的方法,实际上都是创建了全新的String对象。
package com.lyj.string;
/*
* String是不可变的
*/
public class StringDemo {
public static void main(String[] args) {
String s1 = "lyj";
System.out.println(s1);
String s2 = upcase(s1);
System.out.println(s2);
System.out.println(s1);
}
public static String upcase(String s) {
return s.toUpperCase();
}
输出结果是lyj, LYJ, lyj。s.toUpperCase(String s)会创建一个新的String对象,返回时返回指向这个对象的引用。 如果s1不指向新的对象,则它指向的值始终是lyj。
2. String对象是不可变的,可以给String对象加任意多的别名,因为String对象具有只读性,所以指向它的任何引用都不能改变它的值。
package com.lyj.test;
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
String s1 = "lyj";
String s2 = "zky" + s1 + "age";
System.out.println(s2);
}
}
这个例子中,编译器会创建一个StringBuilder对象,用于构造最终的String,并且为每个字符串调用一次StringBuilder的append方法,总计4次。最后调用toString生成结果,并保存为s2.
StringBuilder是java SE5引入的,在这之前java用的StringBuffer.后者是线程安全的,因此开销会大一点,所以在引入StringBuilder操作字符串会更快一点。
3.
public static void main(String[] args) {
String hello = "hello";
String hel = "hel";
String lo = "lo";
/*
* 输出true
* 在"+"两边都是常量字符串,则将两个字符串合并并且在String Pool中查找"hello",然后返回他的内存地址
*/
System.out.println(hello == "hel" + "lo");
/*
* 输出false
* "编译器为了对"hel" + lo语句进行优化,其实会创建一个StringBuilder对象,然后依次调用它的append方法,
* 最后调用toString方法返回一个String对象的引用。
*/
System.out.println(hello == "hel" + lo);
}
4.
public static void main(String[] args) {
/*
* 虽然两个语句都是返回一个String对象的引用,但是jvm对两者的处理方式是不一样的。对于第一种,jvm会马上在heap中创建一个String对象,
* 然后将该对象的引用返回给用户。对于第二种,jvm首先会在内部维护的strings pool中通过String的 equels 方法查找是对象池中是否存放有
* 该String对象,如果有,则返回已有的String对象给用户,而不会在heap中重新创建一个新的String对象;如果对象池中没有该String对象,
* jvm则在heap中创建新的String对象,将其引用返回给用户,同时将该引用添加至strings pool中。
* 注意:使用第一种方法创建对象时,jvm是不会主动把该对象放到strings pool里面的,除非程序调用 String的intern方法。
*/
String s1 = new String("abc");
String s2 = "abc";
String s3 = new String("abc");
System.out.println(s1 == s2);//false
System.out.println(s1 == s3);//false
System.out.println(s2 == s3);//false
// 程序显式将s1放到strings pool中,intern运行过程是这样的:首先查看strings pool
// 有没“abc”对象的引用,没有,则在堆中新建一个对象,然后将新对象的引用加入至
// strings pool中。执行完该语句后,str1原来指向的String对象已经成为垃圾对象了,随时会
// 被GC收集。s1.intern()是在String Pool中的“abc"的引用,s1是在heap中新建“abc”对象的引用。
//分析这类题最好画图,这样比较好理解
System.out.println(s1 == s1.intern());//false
System.out.println(s2 == s1.intern());//true
System.out.println(s2 == s2.intern());//true
System.out.println(s1.intern() == s3.intern());//true
}
分析图如下: