习题解答chapter06
题目
- 借助JDK,选取几个String与StringBuffer、StringBuilder的常用的API,并编写实例测试API的功能。
- 请简述String、StringBuffer、StringBuilder三者之间的共同点与区别,应该分别在何种场景之下使用?
- 为什么不建议在 for循环中使用“+”进行字符串拼接?
- 什么是字符串的编码与解码?请举例说明。
1. 借助JDK,选取几个String与StringBuffer、StringBuilder的常用的API,并编写实例测试API的功能。
- 字符串的值比较和引用比较
String s = new String("Hello");
String t = new String("Hello");
// 字符串值比较和引用比较
if (s == t){
System.out.println("=");
}else {
System.out.println("!=");
}
if (s.equals(t)) {
System.out.println("相等");
} else {
System.out.println("不相等");
}
- concat(String Str)将str附加在当前字符串后生成一个新字符串返回。
// concat(String str)将指定的字符串连接到该字符串的末尾。
String temp = s.concat(t).concat("world");
System.out.println(s.concat(" world"));
System.out.println(s.concat(" world").concat(" !"));
System.out.println(temp);
- 静态方法valueOf负责将其他基本数据类型转换为String。
// 返回boolean参数的字符串的boolean形式。
boolean flag = false;
System.out.println(valueOf(flag) + ", " + getType(valueOf(flag)));
// 返回int参数的字符串的int形式
int i = 5;
System.out.println(valueOf(i) + ", " + getType(valueOf(i)));
// 其他基本数据类型基本相似,不再举例。
- charAt(int index)得到字符串中指定位置的一个字符。
String in = "abcdefghijk";
System.out.println(in.charAt(7));
- 转为数组方法:转为字节数组getBytes、转为字符数组toCharArry、按正则表达式分割成数个子字符串数组的方法split。
/*
* 使用给定的charset将该String编码为一个字节序列,将结果存储到新的字节数组中。
* 此方法总是用此字符集的默认替换字节数组替换格式错误的输入和不可映射字符序列。 当需要对编码过程的更多控制时,应使用CharsetEncoder类。
*/
String a = "Hello Word";
byte b[] = a.getBytes();
System.out.println(new String(b));
for(int j = 0; j < b.length; j++){
System.out.println(b[j]);
}
// 将此字符串转换为新的字符数组。
char[]c = a.toCharArray();
System.out.println(c);
for(int j = 0; j < c.length; j++){
System.out.println(c[j]);
}
// 将此字符串拆分为给定的regular expression的匹配。
// 该方法的工作原理是通过使用给定表达式和限制参数为零调用双参数split方法。 因此,尾随的空字符串不会包含在结果数组中。
String iin = "hui:jia:shuijiao";
for (String retval: iin.split(":")){
System.out.print(retval + " ");
}
- 定位字符串或字符方法indexOf、lastIndexOf。
String d = "Hello Word";
// 返回指定字符第一次出现的字符串内的索引。
System.out.println(d.indexOf("o"));
// 返回指定字符的最后一次出现的字符串中的索引。
System.out.println(d.lastIndexOf("o"));
字符串替换(replace开头)方法,字符串大小转化方法(toUpperCase、toLowerCase),去空格方法(trim),只有头尾空格可以去除。
String l = "Hello Word";
String k = "你好";
System.out.println(l.replace(l, k));
System.out.println(l.replace(l, "HELLO WORD"));
System.out.println(k.replace("你", "大家"));
String gg = "Hello Word";
System.out.println(gg.toUpperCase());
System.out.println(gg.toLowerCase());
String a = " Hello Word ";
System.out.println(a.trim());
2. 请简述String、StringBuffer、StringBuilder三者之间的共同点与区别,应该分别在何种场景之下使用?
String类代表字符串。 Java程序中的所有字符串文字(例如"abc" )都被实现为此类的实例。
字符串不变; 它们的值在创建后不能被更改。 字符串缓冲区支持可变字符串。 因为String对象是不可变的,它们可以被共享。 例如:
String str = "abc";
相当于:
char data[] = {'a', 'b', 'c'};
String str = new String(data);
StringBuffer线程安全,可变的字符序列。 字符串缓冲区就像一个String ,但可以修改。 在任何时间点,它包含一些特定的字符序列,但可以通过某些方法调用来更改序列的长度和内容。
字符串缓冲区可以安全地被多个线程使用。 这些方法在必要时进行同步,以便任何特定实例上的所有操作都按照与所涉及的各个线程所执行的方法调用顺序一致的顺序发生。
StringBuffer的主要StringBuffer是append和insert方法,它们被重载以便接受任何类型的数据。 每个都有效地将给定的数据转换为字符串,然后将该字符串的字符附加或插入到字符串缓冲区。 append方法总是在缓冲区的末尾添加这些字符; insert方法将insert添加到指定点。
例如,如果z是指当前内容为"start"的字符串缓冲区对象,那么方法调用z.append("le")将使字符串缓冲区包含"startle" ,而z.insert(4, "le")会将字符串缓冲区更改为包含"starlet" 。
一般情况下,如果某人是指的一个实例StringBuffer ,则sb.append(x)具有相同的效果sb.insert(sb.length(), x) 。
StringBuilder 一个可变的字符序列。 此类提供与StringBuffer的API,但不保证同步。 此类设计用作简易替换为StringBuffer在正在使用由单个线程字符串缓冲区的地方(如通常是这种情况)。 在可能的情况下,建议使用这个类别优先于StringBuffer ,因为它在大多数实现中将更快。
StringBuilder的主要StringBuilder是append和insert方法,它们是重载的,以便接受任何类型的数据。 每个都有效地将给定的数据转换为字符串,然后将该字符串的字符附加或插入字符串构建器。 append方法始终在构建器的末尾添加这些字符; insert方法将insert添加到指定点。
例如,如果z引用当前内容为“ start ”的字符串构建器对象,那么方法调用z.append("le")将导致字符串构建器包含“ startle ”,而z.insert(4, "le")会将字符串构建器更改为包含“ starlet ”。
关于详细细节可以参考https://blog.csdn.net/kingzone_2008/article/details/9220691,以上部分为JDK文档内容。
3. 为什么不建议在 for循环中使用“+”进行字符串拼接?
阿里开发手册上面不建议使用字符串拼接符“+”,因为“+”会创建新的字符串,导致内存资源浪费。
这样一段代码,我们把生成的字节码进行反编译:
String a = "Hello Word";
String b = "Hello Java";
String g = a + "," + b;
反编译内容:
(new StringBuilder()).append(a).append(",").append(b).toString();
有关字符串拼接内容,可以参考https://www.jianshu.com/p/753f3098ede4
. 什么是字符串的编码与解码?请举例说明。
将unicode字符集转为本地字符集(如GB2312或GBK)的过程叫编码,反之叫解码。
编码:
import java.io.*;
public class CharCode {
public static void printByteArray(String msg,byte[] t){
System.out.println(msg+"****************");
for(int i=0;i<t.length;i++){
System.out.println(Integer.toHexString(t[i])); }
}
public static void printCharArray(String msg,char[] c){
System.out.println(msg+"****************");
for(int i=0;i<c.length;i++){
System.out.println(Integer.toHexString(c[i])); }
}
public static void main(String[] args){
try{
String str = "中文";
System.out.println(str);
printCharArray("unicode:",str.toCharArray()); //unicode字符集中对"中文"二字的对应代码
byte[] b =str.getBytes("GB2312"); //编码:转为本地字符集GBK2312对应的代码
printByteArray("GB2312",b);
byte[] m =str.getBytes("ISO8859-1"); //转为ISO8859-1对应的代码
printByteArray("ISO8859-1",m); // ISO8859-1是英文字符集,没有对应的汉字代码,所以转化错误
}
catch(UnsupportedEncodingException e){
System.out.println("没有相应的字符集!");
}
}
}
解码:
public class Decode {
public static void printByteArray(String msg, byte[] t) {
System.out.println(msg + "****************");
for (int i = 0; i < t.length; i++) {
System.out.println(Integer.toHexString(t[i]));
}
}
public static void printCharArray(String msg, char[] c) {
System.out.println(msg + "****************");
for (int i = 0; i < c.length; i++) {
System.out.println(Integer.toHexString(c[i]));
}
}
public static void main(String[] args) {
byte[] b = new byte[6];
int t = 0, pos = 0;
String s;
try {
while (t != '\n') {
t = System.in.read();
b[pos] = (byte) t;
pos++;
}
printByteArray("本地码", b);
s = new String(b, "GBK");
System.out.println(s);
printCharArray("unicode码", s.toCharArray());
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}