首次发布于我的博客
https://www.elichen.club/
String
String简介
java中String
为引用数据类型,其本身也为一个class文件,实现原理为char
类型数组。(看下图)由于String
类为final
修饰的并且数组char value[]
也为final
修饰,所以String
为不可变类型,赋值后不能改变,为字符串常量
。
举个栗子?
String a = "eli";
String a = "chen";
以上语句看似字符串a发生了改变,从eli
变为chen
,但是String
不可变所说的为字符串本身不可变,不是其引用所指向的对象地址。这里创建了一个新的String对象并使用a引用指向其地址,原来的eli
并没有发生改变而是失去了地址引用,变成了内存中的垃圾。
String之间的比较
我们在比较字符串时我们想比较的是字符串的内容是否相等,因为String
为引用数据类型,String
对象存储的只是指向该字符串堆空间的一个内存地址,使用==
比较并不能得到正确结果,这与我们的初衷违背,因为String
重写了Object
类的equals()
方法,我们在进行字符串比较式必须使用equals()
方法,不能使用==
。
代码演示
代码段1:
String a = "aa";
String b = "aa";
System.out.println(a == b); //true
System.out.println(a.equals(b)); //true
代码段2:
String c = new String("cc");
String d = new String("cc");
System.out.println(c == d); //false
System.out.println(c.equals(d)); //true
代码段3:
String e = "eli" + "chen";
看以上代码发现a==b
也为true
而c==d
为false
,原因是因为java在编译期会将相同的字符串当做一个对象放入常量池,所以a
和b
为同一个对象,==
也为true
。使用new String()
来创建对象会强制创建两个不同的对象,所以c==d
为false
。
以上代码共创建几个对象?
-
代码段1:
String a = “aa”;在字符串常量池创建一个对象"aa",后面b时直接引用该对象,不用再创建,共创建一个对象 -
代码段2:
先在字符串常量池创建一个对象"cc",然后在堆空间创建两个对象,使c和d分别指向它们,共创建3个对象 -
代码段3:
在字符串常量区创建3个对象,分别是"eli" ,“chen”,“elichen”
方法简介
判断功能
//1 equals判断字符串内容是否相等 引用数据类型 ==比较的是内存地址(是不是同一个对象)
String s1 = "aaa";
String s2 = new String("aaa");
System.out.println(s1.equals(s2));
//常量和变量使用equals比较内容时,尽量把常量写在前面
//equalsIgnoreCase 忽略大小写的比较
String str1 = "aaa";
String str2 = "AAA";
System.out.println(str1.equals(str2));
System.out.println(str1.equalsIgnoreCase(str2));
//contains 判断字符串是否包含某内容(子串)
String str = "abcde";
System.out.println(str.contains("ab"));
System.out.println(str.contains("cde"));
System.out.println(str.contains("ac"));
// startsWith endsWith 判断字符串是否以某个值开头 是否以某个值结尾
String str="http://www.sina.com.cn";
System.out.println(str.startsWith("h"));
System.out.println(str.startsWith("http"));
System.out.println(str.endsWith("cn"));
System.out.println(str.endsWith(".cn"));
// isEmpty 判断字符串是否 为空串
String str1 = "";
String str2 = new String();
String str3 = new String("");
String str4 = " ";
System.out.println(str1.isEmpty());
System.out.println(str2.isEmpty());
System.out.println(str3.isEmpty());
System.out.println(str4.isEmpty());
获取功能
// 1 length() 获取字符串长度(由多少个字符组成)
String str = "abc";
int x = str.length();
System.out.println(x);
//2 charAt 获取某个位置上的字符
String str = "abcde";
char c = str.charAt(1);
System.out.println(c);
//3 substring 截取子串
String str = "abcdefg";
String result = str.substring(2); //取到最后
System.out.println(result);
String result2 = str.substring(2,4); // 左闭右开
System.out.println(result2);
//4 indexOf 查找位置
String str = "abcdeabcd";
int idx = str.indexOf("cd");
System.out.println(idx);
int idx2 = str.indexOf("ab",3);
//int idx2 = str.indexOf("ab",-3);// 第2个参数为负数,相当于0
System.out.println(idx2);
int idx3 = str.indexOf("xy");
System.out.println(idx3); // 找不到时,返回-1
//5 lastIndexOf 查找位置 从后向前找
String str = "abcdeabcd";
int idx = str.lastIndexOf("cd");
System.out.println(idx);
int idx2 = str.lastIndexOf("ab",3);
System.out.println(idx2);
int idx3 = str.lastIndexOf("xy");
System.out.println(idx3); // 找不到时,返回-1
转换功能
// 1 getBytes() 将字符串转换成字节数组
String str = "abcd";
byte[] b = str.getBytes();
for(byte bb:b){
System.out.println(bb);
}
// 2 toCharArray() 将字符串转成字符数组
String str = "abcd";
char[] cc = str.toCharArray();
for(char c:cc){
System.out.println(c);
}
// 3 toUpperCase 小写转大写
String str = "abcd";
String str2 = str.toUpperCase();
System.out.println(str2);
//4 toLowerCase 大写转小写
String str = "AbCd";
String str2 = str.toLowerCase();
System.out.println(str2);
//5 concat 用来拼接字符串 和 +的作用相同 . 不同点: + 可以加任何类型 而concat只能拼接字符串
String s1 = "aaa";
String s2 = "bbb";
String s3= s1.concat(s2);
System.out.println(s3);
//6 valueOf 将其他类型转换成字符串 静态方法
int x = 100;
String str = String.valueOf(x);
System.out.println(str+1); // "1001"
int y = 200;
String str2 = y+""; //任何类型和字符串相加结果都是字符串
System.out.println(str2+1); //"2001"
StringBuffer(JDK1.0)
StringBuffer简介
StringBuffer
为可变长字符串,原理与字符串相同,数组为可变长数组,默认容量为16
,创建更长的字符串可以自动扩容。StringBuffer
对象可以被多次修改并不会产生新的对象,进行字符串处理效率高。StringBuffer
的方法都是使用synchronized
修饰的方法,所以StringBuffer
为线程安全的。
StringBuffer方法简介
//StringBuffer构造方法1
StringBuffer sb1=new StringBuffer("Hello");
System.out.println(sb1);
String s1="World";
//StringBuffer构造方法2
StringBuffer sb2=new StringBuffer(s1);
System.out.println(sb2);
//length()返回字符串的长度
System.out.println(sb2.length());
//toString()这个方法重写了Object中的toString()方法,返回String类型的字符串
//输出StringBuffer对象时候,会默认调用此方法
System.out.println(sb2);
//append(String s)方法在原有的字符串后面添加字符串,返回的是添加后的StringBuffer对象
sb1.append(" World");
System.out.println(sb1);
//public StringBuffer deleteCharAt(int index)
//该方法的作用是删除指定位置的字符,然后将剩余的内容形成新的字符串
sb1.deleteCharAt(0);
System.out.println(sb1);//ello World
//public StringBuffer delete(int start,int end)
//从字符缓冲区中从start索引删除到end索引所对应的字符,其中包括start索引不包括end索引对应的值
sb1.delete(1, 3);
System.out.println(sb1);
//public StringBuffer insert(int offset,String str)
//在字符串缓冲区的第offset个字符后面插入指定字符串
sb1.insert(1, "ME");
System.out.println(sb1);
//public StringBuffer reverse(),将字符串反转
sb1.reverse();
System.out.println(sb1);
StringBuilder(JDK1.5)
StringBuilder简介
StringBuilder在JDK5.0新增的,StringBuilder与StringBuffer基本相同只不过不是线程安全的,方法也大致相同。StringBuilder效率更高。
总结
执行速度
- 三者在执行速度方面的比较:StringBuilder > StringBuffer > String
线程安全
- StringBuffer:线程安全的,StringBuilder:非线程安全的
使用策略
- 1.如果要操作少量的数据用String
- 2.单线程操作字符串缓冲区 下操作大量数据用StringBuilder
- 3.多线程操作字符串缓冲区 下操作大量数据用StringBuffer
- 4.不要使用String类的"+"来进行频繁的拼接,因为那样的性能极差的,应该使用StringBuffer或StringBuilder类