String
String是引用类型,不可变;本身是一个class,内部是由char[]
数组表示的,通过private final char[]
字段确保其不可变。
声明String的方式:
String s1 = "Hello!";
String s2 = new String(new char[] {
'H', 'e', 'l', 'l', 'o', '!'});
字符串比较 ==和equals()
equals()
方法能比较出二者内容是否相同;
==
方法只能比较二者是否指向同一个对象;
要注意Java编译器会把所有相同的字符串当作一个对象放入常量池,所以相同字面量的引用是相同的:
String s1 = "hello";
String s2 = "hello";
System.out.println(s1 == s2);
如果字符串内容相同,但指向不同对象,就要用equals()比较:
String s1 = "hello";
String s2 = "HELLO".toLowerCase();
System.out.println(s1 == s2); //false
System.out.println(s1.equals(s2)); //true
常用方法
s1.equalsIgnoreCase(s2); //忽略大小写比较
"Hello".indexOf("l"); // 2
"Hello".lastIndexOf("l"); // 3
"Hello".startsWith("He"); // true
"Hello".endsWith("lo"); // true
"Hello".substring(2); // "llo"
"Hello".substring(2, 4); //"ll" 类似python切片
" \tHello\r\n ".trim(); // "Hello"
"\u3000Hello\u3000".strip(); // "Hello",加强版trim(),类似中文的空格字符\u3000也会被移除
"".isEmpty(); // true,因为字符串长度为0
" ".isEmpty(); // false,因为字符串长度不为0
" \n".isBlank(); // true,因为只包含空白字符
" Hello ".isBlank(); // false,因为包含非空白字符
String s = "hello";
s.replace('l', 'w'); // "hewwo",所有字符'l'被替换为'w'
s.replace("ll", "~~"); // "he~~o",所有子串"ll"被替换为"~~"
String s = "A,,B;C ,D";
s.replaceAll("[\\,\\;\\s]+", ","); // 正则替换,"A,B,C,D"
String s = "A,B,C,D";
String[] ss = s.split("\\,"); // {"A", "B", "C", "D"},注意splite的参数需要用双引号,传入的是正则表达式
String[] arr = {
"A", "B", "C"};
String s = String.join("***", arr); // "A***B***C",String.join()静态方法,从无到有
//String.format()静态方法,生成格式化字符串,也是从无到有
String.format("Hi %s, your score is %.2f!", "Bob", 59.5); //Hi Bob, your score is 59.50!
类型转换
任意类型转String:
//类型转换,String.valueOf()静态方法
String.valueOf(123); // "123"
String.valueOf(45.67); // "45.67"
String.valueOf(true); // "true"
String.valueOf(new Object()); // 类似java.lang.Object@636be97c
String转int,用Integer.parseInt()静态方法:
int n1 = Integer.parseInt("123"); // 123
int n2 = Integer.parseInt("ff", 16); // 按十六进制转换,255
要特别注意,Integer有个getInteger(String)
方法,它不是将字符串转换为int,而是把该字符串对应的系统变量转换为Integer:
Integer.getInteger("java.version"); // 获取系统变量之版本号,11
String转boolean:
boolean b1 = Boolean.parseBoolean("true"); // true
boolean b2 = Boolean.parseBoolean("FALSE"); // false
String转char[],用String.toCharArray():
char[] cs = "Hello".toCharArray(); // String -> char[]
char[] 转 String,可以直接作为实例参数。这里s指向一个新对象,修改cs的值不会影响s:
String s = new String(cs); // char[] -> String
从String的不变性设计可以看出,如果传入的对象有可能改变,需要复制而不是直接引用。例如:
public class Main {
public static void main(String[] args) {
int[] scores = new int[] {
88, 77, 51, 66 };
Score s = new Score(scores);
s.printScores();
scores[2] = 99;
s.printScores();
}
}
class Score {
private int[] scores;
public Score(int[] scores) {
this.scores = scores.clone(); //这里要复制一份,否则类内部的scores[2]会被改为99
}
public void printScores() {
System.out.println(Arrays.toString(scores));
}
}
编码
- ASCII: 1个字节
- GB2312:2个字节,能表示汉字
- Unicode:UCS-2用2个字节,UCS-4用4个字节
- UTF-8:变长编码,用来把固定长度的Unicode编码变成1~4字节的变长编码。比如英文字符的Unicode编码高字节总是00,就有了压缩的空间。UTF-8编码的另一个好处是容错能力强,因为其高字节位能确定一个字符究竟是几个字节,它经常用来作为传输编码。
java中的char类型是2字节的Unicode,可以用getBytes()方法转为相应的编码(始终优先考虑UTF-8编码):
byte[] b1 = "Hello".getBytes(); // 按系统默认编码转换,不推荐
byte[] b2 = "Hello".getBytes("UTF-8"); // 按UTF-8编码转换,推荐
byte[] b2 = "Hello".getBytes("GBK"