String【字符串】
可变字符串和不可变字符串
不可变字符串序列
String
/*
为不可变对象,一旦被创建,就不能修改它的值
对于已经存在的String对象的修改都是重新创建一个新的对象,然后把新的值保存进去
String 是final类,即不能被继承
并且由于String 对象是不可变对象,每次操作Sting 都会重新建立新的对象来保存新的值
这样原来的对象就没用了,就要被垃圾回收.这也是要影响性能的
*/
可变字符串序列
StringBuffer:安全性高效率低 安全的synchronized
StringBuilder:效率高安全性低
/*
是一个可变对象,当对他进行修改的时候不会像String那样重新建立对象
它只能通过构造函数来建立,
StringBuffer sb = new StringBuffer();
note:不能通过赋值符号对他进行赋值.
sb = "welcome to here!";//error
对象被建立以后,在内存中就会分配内存空间,并初始保存一个null.向StringBuffer
中赋值的时候可以通过它的append方法.
*/
可变字符串为什么可变?
首先创建了一个长度为16的数组,当存放数据的时候,首先检查当前数组是否能够装下当前数据,如果存的下直接存放,如果存不下,数组开始扩容,每次扩大 length*2+2,所以说我们可变字符串序列就是因为数组的大小在一直改变
<------不可变字符串String------>
特性
public final class String
字符串在java中是一个类,然后这个类是一个太监类,不能被继承
final
这个字符串变量的value值的引用只能被初始化一次,而且引用没法进行修改
但是数组中的值还是可以被改变的
private
string类中没有提供设置数组的方法,禁止外部的修改
特点
String的默认值为null
注意""和null是不同的,""是一个对象,代表没有内容,length为0,但是null代表指向空,运行时会出现“空指针异常”
String a="abc"; 等同于 String a=new String;
a是一个类类型变量,abc是一个对象
字符串最大的特点就是,一旦被初始化就不可以被改变
对于我们的字符串来讲,如果我们对字符串做了拼接,删除,修改的操作,会重新创建新的字符串
内存视图
内存分析[了解]
栈
堆
方法区
代码
静态变量
字符串常量池
池:提供一个可重复使用,减少对象的创建时间
字符串这种数据类型在日常生活中使用较频繁
常量池中的字符串对象有可能有多个引用同时指向,如果字符串的值是可变的,那其中一个引用把值给它改变了
所有的引用看到的结果都是改变后的, 数据的安全性就得不到保证
就是因为字符串是一个不可变的字符序列,所以每当发生改变的时候都会创建一个新的对象,所以常量池这种机制才能够使用
字符串比较
变量相加就先创建新的字符串,有独立的地址值 如b1="hello" b2="world" b1+b2!=helloworld
字符串和字符串相加就是普通的字符串加字符串 如 "hello"+"world" =helloworld
注意:基本数据类型只比较值,地址一不一样无所谓
引用类型比较地址值
应用
单纯值与值的比较
1 public class TestString { 2 public static void main(String[] args) { 3 4 String a1 = "abcdef"; 5 String a2 = "abcdef"; 6 7 System.out.println(a1 == a2); //true 8 9 }
1 public class TestString { 2 public static void main(String[] args) { 3 4 String b1 = "hello"; 5 String b2 = "world"; 6 7 String b3 = "helloworld"; 8 String b4 = "hello" +"world"; 9 10 System.out.println(b3 == b4); //true 因为只是单纯的字符串和字符串相加,所以比较的是字符串的值 11 12 }
地址值和地址值的比较
public class TestString { public static void main(String[] args) { String b1 = "hello"; String b2 = "world"; String b3 = "helloworld"; String b4 = b1+"world"; System.out.println(b3 == b4); //false 因为对对象b1进行了+的操作,地址值发生改变
}
String中的equals比较
1 public class StringDemo { 2 public static void main(String[] args) { 3 String s1="abc"; 4 String s2=new String("abc"); 5 6 System.out.println(s1==s2); //false 7 System.out.println(s1.equals(s2)); //true 8 9 } 10 }
详细解释
syso(s1==s2) //false
在这句代码中,因为如果对字符串的对象做了拼接,删除,修改的操作,会重新创建新的字符串对象,所以s1和s2比较的是对象的地址值,由于是s1和s2指代的是两个对象,所以返回值为false
syso(s1.equals(s2)) //true
在这句代码中,String类重写了Object类中的equals方法,使得该方法判断字符串内容是否相等,由于"abc"="abc",所以返回值为true
延伸
s1和s2有什么区别?[面试]
s1内存中有一个对象 "abc"
s2内存中有两个对象 "new String"和"abc"
String中的常用方法
判断功能
contains(str):查询是否包含指定的字符串
特殊之处:在indexOf(str)中如果没有所查找的字符或者字符串,会返回-1,所以可以用于对制定字符串是否存在的判断
1 public class TestStringSkill {
2 public static void main(String[] args) {
3
4 String string = "abcdefghijklMnopqrstuvwxyz中发白中发白";
5 boolean flag = string.contains("abcdef");
6 System.out.println(flag); //true
7 }
8 }
startsWith:以XXX开头 endsWith:以XXX结尾
1 public class TestStringSkill {
2 public static void main(String[] args) {
3
4 String string = "abcdefghijklMnopqrstuvwxyz中发白中发白";
5 boolean flag = string.startsWith("abcdefghijklmnopqrstuvwxyz"); //必须是从头开始,从第一个字符开始
6 System.out.println(flag); //false
7 boolean flag1 = string.endsWith("发白"); //必须是从末尾开始,从最后一个字符开始
8 System.out.println(flag1); //true
9 }
10 }
equals:返回值boolean类型 判断字符串内容是否相同,重写了Object的equals方法,比较的是字符串的值,并且不忽略大小写
1 public class TestStringSkill {
2 public static void main(String[] args) {
3 String str1 = new String("abcd");
4 String str2 = new String("abcd");
5 System.out.println(str1 == str2); //false //比较的是地址值
6 System.out.println(str1.equals(str2)); //true //比较的是字符串的值
7 }
8 }
equalsIgnoreCase():判断内容是否相同,并且忽略大小写
1 public class StringDemo {
2 public static void main(String[] args) {
3 Demo.demo1();
4 }
5 }
6
7 class Demo {
8 public static void demo1() {
9 String string = "abc";
10 String string2 = "ABC";
11
12 System.out.println(string.equalsIgnoreCase(string2)); // true
13 System.out.println(string.equals(string2)); // false
14 }
15 }
isEmpty():返回值为boolean,判断字符串中是否有内容,如果返回值为true,则length为0
1 public class StringDemo {
2 public static void main(String[] args) {
3 String string="abcdefghijklmn";
4
5 System.out.println(string.isEmpty()); //false
6
7 }
8 }
注意""和null是不同的,""是一个对象,代表没有内容,length为0,但是null代表指向空,会出现“空指针异常”
1 public class StringDemo {
2 public static void main(String[] args) {
3 Demo.demo1();
4 //Demo1.demo2(); //报空指针异常 java.lang.NullPointerException
5 }
6 }
7
8 class Demo{
9 public static void demo1() {
10 String string="";
11
12 System.out.println(string.length()); //0
13 System.out.println(string.isEmpty()); //true
14 }
15 }
16
17 class Demo1{
18 public static void demo2() {
19 String string=null;
20
21 System.out.println(string.length());
22 System.out.println(string.isEmpty());
23 }
24 }
获取功能
length:返回当前字符串的长度[int型]
1 public class TestStringSkill {
2 public static void main(String[] args) {
3
4 String string = "abcdefghijklMnopqrstuvwxyz中发白中发白";
5 System.out.println(string.length()); //32
6 }
7 }
charAt(int index),根据位置获取位置上的某个字符,从0开始计数,当访问到字符串中不存在的角标时会出现StringIndexOutOfBoundsException
1 public class TestStringSkill {
2 public static void main(String[] args) {
3
4 String string = "abcdefghijklMnopqrstuvwxyz中发白中发白";
5 char c = string.charAt(1);
6 System.out.println(c); //b
7 }
8 }
codePointAt:char类型的字符对应的编码值[ASCII码 阿斯克码]
1 public class TestStringSkill {
2 public static void main(String[] args) {
3
4 String string = "abcdefghijklMnopqrstuvwxyz中发白中发白";
5 int i = string.codePointAt(26);
6 int i1 = string.codePointBefore(27);
7 int i2 = string.codePointCount(0, 26);
8 System.out.println(i); //20013
9 System.out.println(i1); //20013
10 System.out.println(i2); //26
11 }
12 }
hashCode:获取对象的哈希值,如果两个对象equals那么他们的hashcode一定相同,但hashcode相同不一定equals
1 public class TestStringSkill {
2 public static void main(String[] args) {
3 String str1 = new String("abcd");
4 String str2 = new String("abcd");
5 System.out.println(str1.hashCode()); //2987074
6 System.out.println(str2.hashCode()); //2987074
7 }
8 }
indexOf(int ch):返回当前字符串所在的索引值[位置],返回的是ch字符在字符串中第一次所出现的位置
indexOf(String ch):返回当前字符串所在的索引值[位置],返回的是ch字符串在字符串中第一次所出现的位置
注意:如果没有所查找的字符或者字符串,会返回-1,所以可以用于对制定字符串是否存在的判断
1 public class TestStringSkill {
2 public static void main(String[] args) {
3 String string = "abcdefghijklMnopqrstuvwxyz中发白中发白";
4 int i = string.indexOf("b");
5 int i1 = string.indexOf(122);
6 int i2 = string.lastIndexOf("中");
7 System.out.println(i); //1
8 System.out.println(i1); //25
9 System.out.println(i2); //29
10 }
11 }
indexOf(int ch,int fromIndex):从fromIndex指定位置开始,获取字符ch在字符串中出现的位置
indexOf(String ch,int fromIndex):从fromIndex指定位置开始,获取字符串ch在字符串中出现的位置
注意:如果没有所查找的字符或者字符串,会返回-1,所以可以用于对制定字符串是否存在的判断
1 public class StringDemo {
2 public static void main(String[] args) {
3 String string="abcdefghijklmn";
4
5 int i=string.indexOf("i", 5);
6 int i1=string.indexOf("jk", 5);
7
8 System.out.println(i); //8
9 System.out.println(i1); //9
10 }
11 }
lastIndexOf(int ch):返回当前字符串所查的字符最后面所在位置的索引值
lastIndexOf(String ch):返回当前字符串所查的字符最后面所在位置的索引值
1 public class TestStringSkill {
2 public static void main(String[] args) {
3 String string = "abcdefghijklMnopqrstuvwxyz中发白中发白";
4
5 int i2 = string.lastIndexOf("中");
6
7 System.out.println(i2); //29 //返回的是最后面的中所在的索引值
8 }
9 }
转换功能
将字符数组转换为字符串
构造函数:String(char[]) :将字符数组的全部内容转成字符串
String(char[],offset,count) :将字符数组的一部分转成字符串 offset:起始位置 count:取得个数
1 public class StringDemo1 { 2 public static void main(String[] args) { 3 char[] arr={'a','b','c','d','e','f','g'}; 4 5 String string=new String(arr); 6 7 System.out.println(string); //abcdefg 8 9 } 10 }
1 public class StringDemo1 { 2 public static void main(String[] args) { 3 char[] arr={'a','b','c','d','e','f','g'}; 4 5 String string=new String(arr,2,3); 6 7 System.out.println(string); //cde 8 9 } 10 }
将字节数组转换为字符串
构造函数:String(byte[]) :将字符数组的全部内容转成字符串
String(byte[],offset,count) :将字符数组的一部分转成字符串 offset:起始位置 count:取得个数
1 public class StringDemo1 { 2 public static void main(String[] args) { 3 byte[] arr = { 'a', 'b', 'c', 'd', 'e', 'f', 'g' }; 4 5 String string1 = new String(arr); 6 7 String string = new String(arr, 2, 3); 8 9 System.out.println(string); // 10 System.out.println(string1); // abcdefg 11 12 } 13 }
toCharArray():将字符串转成字符数组
1 public class StringDemo1 { 2 public static void main(String[] args) { 3 String string = "abcdefg"; 4 5 char[] arr = string.toCharArray(); 6 for (int i = 0; i < arr.length; i++) { 7 System.out.println(arr[i]); 8 //a b c d e f g 9 } 10 11 } 12 }
getBytes:将字符串转换成字节数组
注意:字符串和字节数组在转换过程中是可以指定编码表的
1 public class TestStringSkill {
2 public static void main(String[] args) {
3 String string = "abcdefghijklMnopqrstuvwxyz中发白中发白";
4 byte[] bytes = string.getBytes();
5 for (int i = 0; i < bytes.length; i++)
6 {
7 System.out.print(bytes[i]+" "
8
9 };
10
11 输出:97 98 99 100 101 102 103 104 105 106 107 108 77 110 111 112 113 114 115 116 117 118 119 120 121 122 -42 -48 -73 -94 -80 -41 -42 -48 -73 -94 -80 -41
12
13 注意:此方法不可以用于中文,否则会出现负数
替换功能
replace(oldchar,newchar):替换,退还之后相当于返回一个新的字符串,原字符串不改变
1 public class StringDemo1 { 2 public static void main(String[] args) { 3 4 String string = "abcdefghijklMnopqrstuvwxyz中发白中发白"; 5 String newstring = string.replace("abc", "_"); 6 System.out.println(newstring); // _defghijklMnopqrstuvwxyz中发白中发白 7 System.out.println(string); // abcdefghijklMnopqrstuvwxyz中发白中发白 8 } 9 }
切割操作
split:切割/拆分字符串
1 public class TestStringSkill {
2 public static void main(String[] args) {
3
4 String string = "abcdefghijklMnopqrstuvwxyz中发白中发白";
5 String[] ss = string.split("xyz"); //从xyz开始拆分 xyz不会显示 注意要定义为数组,因为结果是两组数据
6 for (int i = 0; i < ss.length; i++) {
7 System.out.println(ss[i]); //abcdefghijklMnopqrstuvw
8 中发白中发白
9 }
10 }
11 }
字串
substring(begin,end) :截取字符串,如果角标不存在,会出现角标越界异常
substring(begin)::截取字符串 ,如果角标不存在,会出现角标越界异常
1 public class StringDemo1 { 2 public static void main(String[] args) { 3 4 String string = "abcdefghijklMnopqrstuvwxyz中发白中发白"; 5 String news = string.substring(1, 5); // 注意(1,5)代表1到5,包含1,不包含5 6 String news1 = string.substring(1, string.length()); 7 String news2 = string.substring(1); 8 9 System.out.println(news); // bcde 10 System.out.println(news1); // bcdefghijklMnopqrstuvwxyz中发白中发白 11 System.out.println(news2); // bcdefghijklMnopqrstuvwxyz中发白中发白 12 } 13 }
转换、去除空格、比较功能
toLowerCase/toUpperCase:转换为大小写
1 public class TestStringSkill {
2 public static void main(String[] args) {
3 System.out.println(string.toLowerCase() + "----" + string.toUpperCase()); //abcdefghijklmnopqrstuvwxyz中发白中发白----ABCDEFGHIJKLMNOPQRSTUVWXYZ中发白中发白
4
5 }
6 }
trim:去掉前后两端的空格
1 public class StringDemo1 { 2 public static void main(String[] args) { 3 String string4 = " Hello Bjsxt "; 4 System.out.println(string4.trim()); //Hello Bjsxt 5 } 6 }
compareTo:比较两个字符串的大小 大于正数 小于负数 相等0 ,考虑大小写,而且小写字母比大写字母大
一个一个字符,比较的是ASCII码
1 public class TestStringSkill {
2 public static void main(String[] args) {
3 String string1 = "a";
4 String string2 = "A";
5 System.out.println(string1.compareTo(string2)); //32 比较,不忽略大小写
6 System.out.println(string1.compareToIgnoreCase(string2)); //0 比较,忽略大小写
7 }
8 }
连接字符串功能
concat:连接字符串,但会创建一个新的字符串并返回
1 public class TestStringSkill {
2 public static void main(String[] args) {
3
4 String string = "abcdefghijklMnopqrstuvwxyz中发白中发白";
5 String ss = string.concat("东南西北");
6 System.out.println(ss == string); //false
7 }
8 }
<------可变字符串StringBuffer/StringBuilder------>
StringBuffer
字符串缓冲区,是一个容器
(1)长度是可以变化的
(2)可以直接操作多个数据类型
(3)最终会通过toString方法变成字符串
C create U update R read D delete
1.存储
StringBuffer append():将指定数据作为参数添加到已有数据的结尾处
因为时容器,所以stringBuffer和stringBuffer1指向的是同一个对象,所以相等
写法一
1 public class Exam1 { 2 public static void main(String[] args) { 3 StringBuffer stringBuffer = new StringBuffer(); 4 stringBuffer.append("ABC"); 5 stringBuffer.append(true); 6 7 StringBuffer stringBuffer1 = stringBuffer.append(1); 8 9 System.out.println(stringBuffer == stringBuffer1); // true 10 System.out.println(stringBuffer.toString); // ABCtrue1 11 System.out.println(stringBuffer1.toString); // ABCtrue1 12 } 13 }
写法二[方法调用链]
1 public class Exam1 { 2 public static void main(String[] args) { 3 StringBuffer stringBuffer = new StringBuffer(); 4 5 stringBuffer.append("ABC").append(true).append(1); 6 7 System.out.println(stringBuffer.toString); // ABCtrue1 8 } 9 }
StringBuffer insert(index,数据):可以将数据插入到指定index位置,从index的位置开始插入
1 public class Exam1 { 2 public static void main(String[] args) { 3 StringBuffer stringBuffer = new StringBuffer(); 4 5 stringBuffer.append("ABC").append(true).append(1); 6 7 stringBuffer.insert(1, "MM"); 8 System.out.println(stringBuffer.toString()); // AMMBCtrue1 9 } 10 }
2.删除
StringBuffer.delete(int start,int end):删除缓冲区中的数据,包含start,不包含end
StringBuffer.deleteCharAt(index):删除指定位置的字符
清空 StringBuffer.delete(0,StringBuffer.length) 我、因为不包含end所对应的位置,所以是length而不是length-1
删除一个字符 StringBuffer.delete(x,x+1); StringBuffer.deleteCharAt(x);
1 public class Exam1 { 2 public static void main(String[] args) { 3 delete(); 4 } 5 6 public static void delete() { 7 StringBuffer stringBuffer = new StringBuffer("abcde"); 8 // 删除包含1不包含3的位置字符 9 // stringBuffer.delete(1, 3); 10 // System.out.println(stringBuffer); // ade 11 12 // 清空缓冲区 13 // stringBuffer.delete(0, stringBuffer.length()); 14 // System.out.println(stringBuffer.toString()); 15 16 // 删除一个字符 17 stringBuffer.delete(2, 3); // abde 18 // stringBuffer.deleteCharAt(2); //abde 19 System.out.println(stringBuffer.toString()); // abde 20 } 21 }
3.获取
char charAt(int index):获取指定索引位置的值
int indexOf(String str):返回指定字符串在字符串中第一次出现的位置
int lastIndexOf(String str):返回指定字符串在字符串中最后一次出现的位置
length():返回长度信息
String substring(int start,int end) 注意这个方法还是用String不是用StringBuffer:截取字符串 [x,y)
1 public class Exam1 { 2 public static void main(String[] args) { 3 search(new StringBuffer("ABCDEFAG")); 4 } 5 6 public static void search(StringBuffer stringBuffer) { 7 8 9 System.out.println(stringBuffer.charAt(2)); //C 10 System.out.println(stringBuffer.indexOf("D")); //3 11 System.out.println(stringBuffer.lastIndexOf("A")); //6 12 13 System.out.println(stringBuffer.length()); //8 14 15 String string=new String("ABCDEFAG"); 16 17 System.out.println(string.substring(1,3)); //BC 18 } 19 }
4.修改
StringBuffer.replace(int start,int end,String str):替换指定位置内容[是改变原字符串,不新建字符串]
StringBuffer.setCharAt(index,char ch):修改一个位置的一个字符
StringBuffer.reverse:反转当前字符串
StringBuffer.getChars(int srcBegin,int srcEnd,char[] dst,int dstBegin):将缓冲区中指定数据存储到指定字符数组中
字符起始位置 字符结束位置 数组 数组存储启示位置
1 public class Exam1 { 2 public static void main(String[] args) { 3 StringBuffer stringBuffer=new StringBuffer("ABCDEFG"); 4 5 Test test=new Test(); 6 test.demo(stringBuffer); 7 } 8 } 9 10 class Test{ 11 12 public static void demo(StringBuffer stringBuffer) { 13 stringBuffer.replace(1, 4, "H"); // [1,4) 14 15 System.out.println(stringBuffer); // AHEFG 16 17 stringBuffer.setCharAt(2, 'M'); 18 System.out.println(stringBuffer); // ABMDEFG 19 20 stringBuffer.reverse(); 21 System.out.println(stringBuffer); // GFEDCBA 22 23 char []abc=new char[10]; 24 25 stringBuffer.getChars(1, 4, abc, 1); 26 27 System.out.println(abc); // BCD ; 28 29 } 30 }
StringBuilder[和StringBuffer功能一样]
JDK1.5版本之后出现了StringBuilder
区别:
StringBuffer:线程同步,安全
StringBuilder:线程不同步,不安全
推荐:多线程StringBuffer 单线程StringBuilder
以后开发建议使用StringBuilder,效率高
JAVA升级三因素:
1.提高效率
2.简化书写
3.提高安全性