原则:
1.字符串使用就采用直接赋值
2. 字符串相等比较
(1)字符串内容比较就使用equals()实现;
(2) == 本身是进行数值(int类型)比较的,如果现在用于对象比较,不是比较内容是否相同,而是比较俩个引用是否指向同一个对象
字符串拼接时,只有纯常量的拼接("+")不会转为StringBuilder,直接在常量池内寻找是否存在已有值。否则,只要存在一个字符串变量str的"+",都会转为StringBuilder调用append()。
String str1 = "abc";
String str2 = "ab";
String str3 = "c";
// String -> StringBuilder.append()
// StringBuilder用toString()返回String,return new String(value,0,count)
String str4 = str2 + str3;
String str5 = str2 + str3;
String str6 = new String("abc");
String str7 = "ab" + "c";
String str8 = str2 + "c";
System.out.println(str1 == str6);//false
System.out.println(str1 == str4);//false
System.out.println(str4 == str5);//false
System.out.println(str1 == str7);//true
System.out.println(str1 == str8);//false
3. 字符串不可变
所有的语言对于字符串的底层实现,都是字符数组,数组的最大缺陷就是长度固定。在定义字符串常量时,它的内容不可改变。
String str = "hello" ;
for(int x = 0 ; x<1000 ; x++) {
str += x ;
}
System.out.println(str);
以上类型的代码不可用,会产生大量的垃圾空间。字符串对象的引用一直在改变
为什么 String 要不可变?
- 方便实现字符串对象池. 如果 String 可变, 那么对象池就需要考虑何时深拷贝字符串的问题了.
- 不可变对象是线程安全的.
- 不可变对象更方便缓存 hash code, 作为 key 时可以更高效的保存到 HashMap 中.
4. String类的设计使用了共享设计模式
在JVM底层实际上会自动维护一个对象池(字符串对象池),如果现在采用了直接赋值的模式进行String类的对象实例化操作,那么该实例化对象(字符串内容)将自动保存到这个对象池之中。
如果下次继续使用直接赋值的模式声明String类对象,此时对象池之中如若有指定内容,将直接进行引用;如若没有,则开辟新的字符串对象而后将其保存在对象池之中以供下次使用,所谓的对象池就是一个对象数组(目的就是减少开销)
5. String类中俩种实例化的区别
(1)直接赋值:只会开辟一块堆内存空间,并且该字符串对象可以自动保存在对象池中以供下次使用。
(2) 构造方法:会开辟两块堆内存空间,其中一块成为垃圾空间,不会自动保存在对象池中,可以使用intern()方法手工入池。
还有一种实例的方法方法将字符数组全部转换为字符串
char[] cha = new char[]{'w', 'w', 'o'};
String s = new String(cha);
6.字符串和字符数组相互转换
将部分字符数组中的内容变为字符串:public String(char value[],int offset,int count )
7.字符串和字节数组相互转换
8.字符串比较
“==”:进行的是数值比较,比较俩个字符串对象的内存地址数值
“equals()”:进行字符串内容的比较
推荐使用方式二:一旦 str 是 null, 方式一的代码会抛出异常(java.lang.NullPointerException), 而方式二不会.
String str = new String("Hello");
// 方式一
System.out.println(str.equals("Hello"));
// 方式二
System.out.println("Hello".equals(str));
compareTo()是一个可以区分大小关系的方法,输出相差的ACSCII码值
9.字符串查找
使用indexOf(),lastIndexOf()需要注意的是如果内容重复,它只能返回查找的第一个位置
10.字符串替换
替换所有内容,替换首个内容. 由于字符串是不可变对象, 替换不修改当前字符串, 而是产生一个新的字符串.
11.字符串截取
指定位置截取是左闭右开
12.字符串转大写、转小写
System.out.println(string.toUpperCase());//转大写
System.out.println(string.toLowerCase());//转小写
//String类中没有首字母大写的操作,自己实现
public static String firstUpper(String str) {
//判断是不是空的
if ("".equals(str) || str == null) {
return str;
} else if (str.length() <= 1) {
return str.toUpperCase();
} else return str.substring(0, 1).toUpperCase() + str.substring(1);
//else return str.substring(0, 1).toUpperCase().concat( str.substring(1));
//str.concat(str1)等价于+,字符串连接,不入池
}
13. 字符串的拆分
注意返回类型使String[]数组
String b = "hello java ! !";
//以空格全部拆分
String[] b1 = b.split(" ");
//以空格部分拆分,拆分成三部分
//hello
//java
//! !
String[] b2 = b.split(" ", 3);
for (String b3 : b2) {
System.out.println(b3);
}
14.去掉字符串中的左右空格,保留中间空格
String string=" hello java ";
System.out.println(string);
System.out.println(string.trim());
// hello java
//hello java