31、String s ="Hello";s = s + " world!";这两行代码执行后,原始的String对象中的内容到底变了没有?
没有,String类为不可变量,对象被创建后,只能读,不改修改,s
= s+ " world!"是装引用s指向了一个新的字符串"Hello world!"。
s = s+ "
world!"在JDK1.5以前版本相当于:
s = new StringBuffer(String.valueOf(s)).append(" world!").toString();
s = s+ "
world!"在JDK1.5及以后版本相当于:
s = new StringBuilder(String.valueOf(s)).append("
world!").toString();
32、是否可以继承String类?
String类是final类故不可以继承,而且String为不可变量,只能读不能修改。
补充:
常用的值类大都为final类,例如:Byte、Character、Short、Integer、Long、Float、Double、Boolean、String、StringBuffer、StringBuilder,但Date、BigInteger、BigDecimal都是非final类,但原则上尽量不继承这些类。
33、String s = new String("xyz");创建了几个String Object?二者之间有什么区别?
两个对象。一个是"xyz",为缓冲区对象。另一个是new出来的String对象。
这两个对象的值相同,但不是同一个对象。
补充,新建对象有几种方式?
1. 使用new关键字
2. 使用反射,调用newInstance
3. 使用clone方法
4. 使用序列化与反序列化
5. 动态代理(Proxy类和CGLIB)
Stringaaa = "aaa";
Stringbbb = "bbb";
Stringaaabbb = "aaabbb";
System.out.println("aaa"+"bbb"=="aaabbb");// true
System.out.println("aaa"+"bbb"==aaa+bbb);// false
System.out.println("aaa"+"bbb"==aaabbb);// true
System.out.println("aaa"+bbb=="aaabbb");// false
System.out.println("aaa"+bbb==aaabbb);// false
System.out.println(aaa+bbb=="aaabbb");// false
System.out.println(aaa+bbb==aaabbb);// false
System.out.println("aaa"+"bbb"==aaabbb.intern());// true
补充例题2:
finalString aaa = "aaa";
finalString bbb = "bbb";
Stringaaabbb = "aaabbb";
System.out.println("aaa"+"bbb"=="aaabbb");// true
System.out.println("aaa"+"bbb"==aaa+bbb);// true
System.out.println("aaa"+"bbb"==aaabbb);// true
System.out.println("aaa"+bbb=="aaabbb");// true
System.out.println("aaa"+bbb==aaabbb);// true
System.out.println(aaa+bbb=="aaabbb");// true
System.out.println(aaa+bbb==aaabbb);// true
System.out.println("aaa"+"bbb"==aaabbb.intern());// true
这两个例子显示了字符串相加产生多少个对象的结果,原因是JVM对字符串相加进行了特殊的优化处理。
在第一个例子中:
"aaa"+"bbb",+号两侧的值都是字符串常量,因此结果也必然是字符串常量,因此编译时可以优化为"aaabbb",和=号右侧的字符串相同,结果都放在了字符串的常量池,是同一对象。
在第一个例子中,aaa和bbb两个变量不是final类型,因此当"aaa"+bbb在JVM编译时,不能确定bbb的值是否在运行时没有被改变过,因此不能进行优化,在运行到此句时,会产生一个新的"aaabbb"字符串对象,而不是池中的字符串对象,得到false。
在第二个例子中,aaa和bbb两个变量都是final类型,因此当"aaa"+bbb在JVM编译时,能确定bbb的值,因此可以在编译期进行优化,得到池中的字符串"aaabbb",因此结果为true。
34、String和StringBuffer的区别
这两个类都实现了CharSequence接口。
1. 类型不同,因为不是一个类,也没有继承关系,做参数时不能共用
2. String对象是不可变对象,不能修改值。而StringBuffer是可变对象,能修改值。
3. 拼接字符串时,String会产生新对象,而StringBuffer只是增加新字符,不产生新对象,因此效率高。
4. String覆盖了equals方法和hashCode方法,而StringBuffer没有覆盖equals方法和hashCode方法,所以,将StringBuffer对象存储进Java集合类中时会出现问题。
34.1、StringBuffer和StringBuilder的区别
相同之处,这两类都是可变长的字符串存储类,都实现了CharSequence接口
1. 类型不同,因为不是一个类,也没有继承关系,做参数时不能共用
2. StringBuffer为线程安全类,StringBuilder为线程非安全类
3. StringBuffer性能低,StringBuilder性能高,如果在局部优先使用StringBuilder
4. JDK在1.5之前,字符串相加使用StringBuffer对象,在1.5之后使用StringBuilder对象
35、如何把一段逗号分割的字符串转换成一个数组?
[if !supportLists]1. [endif]用正则表达式,代码大概为:String [] result = orgStr.split(“,”, -1);
[if !supportLists]2. [endif]用 StingTokenizer ,代码为:
StringTokenizer tokener =newStringTokenizer(s,",");
String[] result =newString[tokener.countTokens()];
Integer i = 0;
while(tokener.hasMoreTokens()) {
result[i++] =tokener.nextToken();
}
[if !supportLists]3. [endif]最笨的办法,用String.indexOf()
intindex = -1;
intoldIndex = 0;
List ss =newArrayList();
while((index =s.indexOf(',', index + 1)) != -1) {
ss.add(s.substring(oldIndex,index));
oldIndex = index+ 1;
}
if(s.charAt(s.length() - 1) == ',') {
ss.add("");
}
String[] array = ss.toArray(newString[ss.size()]);
System.out.println(Arrays.toString(array));