一、字符连接问题
问题:‘H’+'a'的结果是什么? 169
分析:
(1)"+"有两种用法:
- 字符串连接:两个操作数之一一定要是String
- 加法:一般的加法
(2)对于字符,+并没有什么重载方式能够连接两个字符,因此只能执行加法。
(3)对于字符的加法,可以转换成int然后执行加法。
(4)String提供了String.valueOf(char)可以将字符转换成String.
(5)StringBuilder提供
解决方法:
(1)String.valueOf('H')+String.valueOf('c');
(2)""+'H'+'a'
public class PuzzleDemo11{
public static void main(String args[]){
System.out.println("H"+"a");
System.out.println('H'+'a');
char c1 = 'H';
char c2 = 'a';
StringBuilder sb = new StringBuilder();
sb.append(c1);
sb.append(c2);
System.out.println("解决方法1:"+sb);
System.out.println("解决方法2:"+'H'+'a');
System.out.println("解决方法3:"+ String.valueOf(c1)+String.valueOf(c2));
}
}
二、字符数组打印问题
问题:
char[] c= {'1','2'};
System.out.println(c);
System.out.println(""+c);
分别打印什么?
12
[C@1234
分析:
(1)字符数组是继承自Object类,但是并没有重载toString()方法,因此如果c.toString()调用的是Object的toString方法。
(2)println重载了println(char[]),因此可以正常打印字符数组。
(3)String.valueOf(char[])也可以将字符数组转换成一个String。
解决方案:
(1)System.out.println(c);
(2)System.out.println(String.valueOf(c));
public class PuzzleDemo12{
public static void main(String args[]){
char[] c = {'1','2','3'};
System.out.println("原来:"+c);
System.out.print("修改1:");
System.out.println(c);
System.out.println("修改2:"+String.valueOf(c));
System.out.println("字符数组调用toString:"+c.toString());
}
}
三、享元模式探究
问题:
String str1 = "123";
String str2 = "123";
System.out.println(str1==str2);
打印结果是什么? true
分析:
(1)这是享元模式的体现,因为如果两个变量有相同的字符串,为了减少内存开销,则两个变量都指向同一个堆内存。
(2)不仅是String,包括int也是一样.
比如:
int i1 = 5000;
int i2 = 5000;
i1==i2返回true。
public class PuzzleDemo13{
public static void main(String args[]){
final String pig = "length: 10";
final String dog = "length: "+pig.length();
System.out.println("pig和dog是否是同一引用:"+(pig==dog));
System.out.println("pig和dog内容是否相同:"+pig.equals(dog));
String str1 = " abc ";
String str2 = " abc ";
System.out.println("str1和str2是否是同一引用:"+(str1==str2)); //享元模式
int i1 = 5000000;
int i2 = 5000000;
System.out.println(i1==i2);
}
}
四、Unicode转义字符和转义字符序列
Unicode转义字符:以\u****形式表示的字符。
转义字符序列:\*形式的字符。
五、注释不会影响编译?不!
问题:
// \uaaa
能通过编译吗?不能。
分析:
(1)在编译之前,程序会把Unicode转义字符转换成Unicode字符,判断依据就是寻找\u开头,如果转换不成功,则出错。
(2)Unicode转义字符一定要合法,就算在注释中,也会被检查。
(3)尽量不要使用Unicode转义字符,因为Unicode转义字符减少了可读性。
六、字符集惹的祸
问题:说出:
(1)String(byte[]);
(2)String(byte[],Charset);的区别。
分析:
(1)String(byte[])使用平台默认的字符集来解码byte数组构造一个新的String,然而给定字节有时在默认字符集上并非有效。
(2)字符集是字节序列和字符序列的转换方式。
结论:
每当一个byte数组转换成一个String对象时,都要显式指定字符集。
import java.nio.charset.Charset;
public class PuzzleDemo18{
public static void main(String args[]) throws Exception{
System.out.println("默认字符集:" + Charset.defaultCharset() );
byte[] bytes = new byte[256];
for(int i=0;i<256;i++){
bytes[i] = (byte)i;
}
String str1 = new String(bytes,"ISO-8859-1");
for(int j=0,n=str1.length();j<n;j++){
System.out.print((int)str1.charAt(j)+" ");
}
}
}
七、StringBuffer初始化问题
问题:
StringBuffer sb = new StringBuffer('M');
在sb中的内容是什么?
答案:空。
分析:
(1)首先列出StringBuffer的构造器:
- StringBuffer(String str)
- StringBuffer(int capacity)
- StringBuffer()
因此没有类似于StringBuffer(char ch)的构造器,而char是一个无符号的字符,可以通过类型转换变成一个int值,调用中间的构造器。
结论:char应该把他看成int,而不是一个String。
八、栅栏柱错误:Random的小细节
Random rnd=new Random();
rnd.nextInt(int n );的规范是选取0~n-1之间的整数(注意n是不包含的)
栅栏柱错误:在处理长度、范围时必须确定端点是否包含在内。
import java.util.Random;
public class PuzzleDemo23{
public static void main(String args[]){
Random rnd = new Random();
String[] sarray = {"Main","Gain","Pain"};
System.out.println(sarray[rnd.nextInt(3)]);
StringBuffer buf = new StringBuffer('H');
System.out.println("内容:"+buf);
StringBuffer buf2 = new StringBuffer("H");
System.out.println("内容:"+buf2);
}
}