1.String
1.1 String概述
(1)String类在java.long包下,使用时不需要导包。
(2)String类代表字符串,java程序中的所有字符串文字(如“abc”)都被实现为此例的实例,也就是说,java程序中所有的双引号字符串,都是String类的对象。
(3)字符串不可变,它们的值在创建后不能被更改。
(4)String类是使用final修饰符修饰的,说明它没有子类,不可被继承。
1.2 String构造方法
(1)String()创建一个空白字符串对象,不含有任何内容;
(2)String(byte[ ] bys,int offset,int length)根据字节数组内容创建字符串对象,int offset-----数组的起始位置,int length-----被转换的字节个数);
(3)String(char[ ] chs,int offset,int length)根据字符数组内容创建字符串对象,int offset-----数组的起始位置,int length-----被转换的字符个数;
(4)String(Sting original) 字符串常量创建字符串对象;比如String s=”abc”;
(5)String(StringBuffer buffer)--将StringBuffer转换成字符串
String(StringBuilder builder)--将StringBuilder转换成字符串
例:
public class StringTest {
public static void main(String[] args) {
//String()创建一个空白字符串对象,不含有任何内容
String str1=new String();
//String(byte[ ] bys,int offset,int length)根据字节数组内容创建字符串对象
byte bys[]={97,98,99,100};
//String str2=new String(bys);这个没错可以的
//String str2=new String(bys,1,3);//输出bcd
String str2=new String(bys,0,bys.length);
System.out.println("str2=="+str2);
//String(char[ ] chs,int offset,int length)根据字符数组内容创建字符串对象
char chs[]={'a','b','c','d'};
String str3=new String(chs,0,chs.length);
System.out.println("str3=="+str3);//abcd
//String(Sting original) 字符串常量创建字符串对象;
String str4=new String("hello,world");
//也可以简化为
String str5="hello,world";
System.out.println("str4=="+str4);
System.out.println("str5=="+str5);
}
}
1.3 String对象的特点
(1)通过new创建的字符串对象,每一次new都会申请一个内存空间,虽然内容相同,但是地址值不同。
例:
char[] chs={'a','b','c'};
String s1=new String(chs);
String s2=new String(chs);
首先JVM会创建一个字符数组,然后每一次new的时候都会有一个新的地址,只不过s1和s2参考的字符串内容是相同的。
(2)以“ ”方式给出的字符串,只要字符序列相同(顺序和大小写),无论在程序代码中出现几次,JVM都只会建立一个String对象,并在字符串常量池中。
比如
String s1=“abcd”;
String s2=“abcd”;
这个首先JVM会建立一个String对象放在字符串常量池中,并给s1参考,然后s4直接参考字符串常量池中的String对象,它们本质上是同一个对象。
具体参考下图
题:String s1=new String("abc");创建了几个对象
答:2个,首先创建一个String对象“abc”在常量池中 ,然后new了一个对象在堆区中。
1.4 字符串的比较
使用==做比较
- 基本类型:比较的是数据值是否相同
- 复合类型:比较的是地址值是否相同
字符串是对象,它比较内容是否相同,是通过一个方法来实现的,这个方法叫:equals()
例:
public class Test {
public static void main(String[] args){
//构造方法的方式得到对象
char[] chs={'a','b','c'};
String s1=new String(chs);
String s2=new String(chs);
//直接赋值的方式得到对象
String s3="abc";
String s4="abc";
System.out.println(s1.equals(s3));//true
System.out.println(s1.equals(s4));//true
System.out.println(s3.equals(s4));//true
}
}
面试题:”==” 与 equals方法的区别?
1.“==”常用来比较基本数据类型,8种基本数据类型有byte、short、long、double、char、int、float、boolean,因为变量直接存储的就是他们的值,所以用"=="去比较,比较的就是他们的值。但是复合数据类型用“==”比较的是他的堆内存地址【引用地址】。
2.“equals”对于复合数据类型比较的也是它的堆内存地址(不能作用于基本数据类型的变量)。由于String类重写了equals方法所以String类“equals”比较的是存储对象的内容是否相等。
2.String的常用方法
String的常用方法(对象.蓝色) | 作用 |
char charAt(int index) | 从原始字符串中得到指定位置的字符元素 |
String concat(String str) | 将指定的字符串连接到该字符串的末尾 |
boolean contains(CharSequence s) | 判断指定的字符串数据是否在原始字符串中存在 |
boolean endsWith(String suffix) | 测试此字符串是否以指定的后缀结尾 |
boolean startsWith(String prefix) | 测试此字符串是否以指定的前缀开头 |
byte [ ] getBytes() byte[ ] getBytes(String charsetName) | 将字符串通过默认的字符编码转换成字节数组 将字符串通过指定的字符编码转换成字节数组 |
int indexOf(String str) | 返回指定子字符串第一次出现在字符串内的索引位置 |
lastIndexOf(String str) | 返回指定子字符串最后一次出现的字符串中的索引 |
boolean isEmpty() | 判断字符串是否为空串,为true时,字符串长度一定为0 |
int length() | 返回此字符串的长度 |
boolean matches(String regex) | 判断字符串数据是否符合正则表达式 |
String replace(CharSequence old, CharSequence new) | 将与字面目标序列匹配的字符串的每个子字符串替换为指定的字面替换序列 |
String[ ] split(String regex) | 通过指定的符号将字符串拆分成一个字符串数组 |
String substring(int beginIndex) String substring(int beginIndex, int endIndex) | 截取从指定的开始位置到字符串结尾的一个子字符串 截取从指定的开始位置到指定的结束位置的一个子字符串 |
char[] toCharArray() | 将此字符串转换为新的字符数组 |
String toLowerCase() | 大写转小写 |
toUpperCase() | 小写转大写 |
String trim() | 去除原始字符串的两头空格 |
例:
public class StringFangFa {
public static void main(String[] args) {
//创建一个字符串对象
String str1=new String("hello,world");
//charAt(int index)从原始字符串中得到指定位置的字符元素
System.out.println(str1.charAt(4));//o
//concat(String str)将指定的字符串连接到该字符串的末尾
System.out.println(str1.concat("!你好"));//hello,world!你好
//contains(CharSequence s)判断指定的字符串数据是否在原始字符串中存在
System.out.println(str1.contains("hello"));//true
System.out.println(str1.contains("hi"));//false
//创建一个名字的数组
String names[]={"张三","李四","王五","李思思","张三丰"};
//endsWith(String suffix)测试此字符串是否以指定的后缀结尾,输出以指定后缀结尾的值
/*遍历数组names
* for(String name:names){
System.out.println(name);
}*/
for(String name:names){
if(name.endsWith("思")){
System.out.println(name);
}
}//李思思
// startsWith(String prefix)测试此字符串是否以指定的前缀结尾,输出指定以前缀开头的值
for(String name:names){
if(name.startsWith("张")){
System.out.println(name);
}
}//张三 张三丰
/*
byte[] getBytes() 将字符串通过默认的字符编码转换成字节数组
byte[] getBytes(String charsetName) 将字符串通过指定的字符编码转换成字节数组
实现功能之前你得有一个字节数组被转换后的字符串,因此先创建字节数组,再创建字符串对象,再转回字节数组
*/
byte byts[]={97,98,99,100};//字节数组
String str2=new String(byts);//转字符串对象
byte byts2[]=str2.getBytes();//默认的字符编码转回字节数组
//byte byts3[]=str2.getBytes("utf-8");//指定的字符编码转回字节数组,有错异常类处理,throws往上抛
//System.out.println(byts2);数组输出的话,需要遍历,直接输出是乱码
for(byte by:byts2){
System.out.println(by);
}
//indexOf(String str)返回指定子字符串第一次出现在字符串内的索引位置
System.out.println(str1.indexOf("orld"));//7
System.out.println(str1.indexOf("llo"));//2
//lastIndexOf(String str)返回指定子字符串最后一次出现在字符串内的索引位置
String str3=new String("hello,world,hello,world,hello");
System.out.println(str3.lastIndexOf("llo"));//26
//isEmpty()判断字符串是否为空串
System.out.println(str3.isEmpty());//false
//length()返回此字符串的长度
System.out.println(str3.length());//29
//replace(CharSequence old, CharSequence new)
//将与字面目标序列匹配的字符串的每个子字符串替换为指定的字面替换序列
System.out.println(str3.replace("or", "zj"));//hello,wzjld,hello,wzjld,hello
//split(String regex)通过指定的符号将字符串拆分成一个字符串数组
String arr[]=str3.split(",");
System.out.println(arr[0]);//hello
System.out.println(arr[3]);//word
/*substring(int beginIndex)
截取从指定的开始位置到字符串结尾的一个子字符串
substring(int beginIndex, int endIndex)
截取从指定的开始位置到指定的结束位置的一个子字符串*/
System.out.println(str3.substring(3));//lo,world,hello,world,hello
System.out.println(str3.substring(3, 15));//lo,world,hel
//toCharArray()将此字符串转换为新的字符数组
//同理你得有字符数组和字符串对象
char ch1[]={'w','e','i'};
String str4=new String(ch1);
char ch2[]=str4.toCharArray();
for(char ch:ch2){
System.out.println(ch);
}
//toLowerCase()大写转小写
//toUpperCase()小写转大写
System.out.println(str4.toLowerCase());//wei
System.out.println(str4.toUpperCase());//WEI
//trim()去除原始字符串的两头空格
System.out.println(str4.trim());
}
}
3. 封装类
通过基本类型提供的封装类的parseXXX(String str)
int parseInt(String str) / double parseDoule(String str)
boolean parseBoolean(String str).......
上面的这一组parseXXX(String str)方法只能被基本类型的封装类调用。
(1)只有8种基本数据类型才有与之对应的封装类型;
(2)封装类----8种基本数据类型对象的复合
基本数据类型 | 封装类类型 |
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
(3)基本数据类型没有可供调用的方法和变量。封装类有可调用的变量和方法。
例如:
double dou=12.5; // double类型的变量,没有可供使用的方法
Double dou=new Double(12.5); //Double的对象,有可供使用的变量和方法。
Double就是double的封装类
(4)基本数据类型只在内存的栈区有数据分配,封装类【复合数据类型】内存的栈区和堆区都有内存分配。
(5)默认初始值不同int---0,Integer---null
(6)装类使用的时候要创建对象,new+构造方法
(7)基本数据类型和对应封装类的区别
基本数据类型 | 封装类 |
基本类型 | 类 |
变量,没有可供调用的方法和变量 | 构造出来都是对象,提供了变量和方法 |
只在内存的栈区有数据分配 | 内存的栈区和堆区都有内存分配 |
有各自默认的数据值 | 默认值为null |
4. 自动装箱和自动拆箱
4.1 自动装箱
自动装箱:将基本数据类型转换成对应的封装类类型
(1)封装类的构造方法;
(2)将基本数据类型变量/数据值直接赋值给对应的封装类变量
public static void main(String[] args) {
//自动装箱
//1.封装类的构造方法
Integer int1=new Integer(100);
//或者
int a=100;
Integer int2=new Integer(a);
//2.将基本数据类型变量/数据值直接赋值给对应的封装类变量
Double dou=12.5;//①
/*
double dou1=12.5;
Double dou2=dou1;②
①②均可*/
4.2 自动拆箱
自动拆箱---将封装类类型转成基本数据类型【直接赋值】
//自动拆箱
Character cr=new Character('A');
char value=cr;
5.String类与基本数据类型相互转换
5.1 基本数据类型转换成String
将基本数据类型转换成String【static String valueOf(基本数据类型的数据值/变量)】例:
int num1=100;
String str01=String.valueOf(num1);
System.out.println(str01.length());
double dou01=12.5;
String str02=String.valueOf(dou01);
5.2 String转换成基本类型
将String转换成基本数据类型,需要依赖于基本数据类型对应的封装类,通过基本数据类型的封装类的静态方法parseXXX(String str)将字符串转换成基本类型。
例:
//我们可以通过基本数据类型的封装类的静态方法parseXXX(String str)将字符串转换成基本类型
String str1="12.5";
double dou3=Double.parseDouble(str1);
System.out.println(dou3+1);
String boo1="true";
boolean boo2=Boolean.parseBoolean(boo1);
if(boo2){
System.out.println("基本类型");
}else{
System.out.println("字符串类型");
}
6.String类与字节数组字节数组转换
6.1 String类与字节数组
(1)String类转换成字节数组
String类的byte[] getBytes()/byte[] getBytes(String charsetName)
(2)字节数组转换String类型
String类的构造方法String(byte[] bytes, int offset, int length)
6.2 String类与字符数组
(1)String类转换成字符数组
String类的”char[] toCharArray()”
(2)字符数组转换String类型
String类的构造方法”String(char[] value, int offset, int count)”
7. StringBulider和StringBuffer
7.1 StringBulider
7.1.1 StringBulider概述
(1)先看一个例子,观察地址值的变化
String s="hello";
s +="world";//等于s=s+"world";
System.out.println(s);
输出helloworld
首先堆区常量池有一个001的hello,栈区有一个S OO1,然后堆区002 world,+后是helloworld,所有有一个003的helloworld,然后赋值给s,栈区的s就变003 。
结论:如果对字符串进行拼接操作,每次拼接,都会构建一个新的String对象,既耗时也浪费存储空间,而这种操作还不可避免,因此java提供了一种类解决这个问题-----StringBulider
(2)StringBuilder是一个可变的字符串类,我们可以把它看成是一个容器,可变是指StringBuilder对象中的内容是可变的。
7.1.2 StringBuilder构造方法
(1)StringBuilder() 构造一个初始容量为16个字符的空StringBuilder对象。
(2)StringBuilder(String str) 构造一个初始化为指定字符串内容的StringBuilder对象。
(3)StringBuilder(CharSequence seq)通过其他的StringBuilder对象创建一个新的StringBuilder对象。
(4)StringBuilder(int capacity) 构造一个由 capacity参数指定的初始容量得空StringBuilder对象
例:
//(1)StringBuilder() 构造一个初始容量为16个字符的空StringBuilder对象。
StringBuilder str1=new StringBuilder();
//(2)StringBuilder(String str) 构造一个初始化为指定字符串内容的StringBuilder对象。
String s="hello";
StringBuilder str2=new StringBuilder(s);
//(3)StringBuilder(CharSequence seq)通过其他的StringBuilder对象创建一个新的StringBuilder对象。
StringBuilder str3=new StringBuilder("hello");
//(4)StringBuilder(int capacity) 构造一个由 capacity参数指定的初始容量的空StringBuilder对象
StringBuilder str4=new StringBuilder(3);
7.1.3 StringBuilder实例方法
返回值 | 方法 |
int | capacity() 返回当前容量 |
int | indexOf(String str) 返回指定子字符串第一次出现的字符串的索引。 |
int | lastIndexOf(String str) 返回指定子字符串最右边出现的字符串的索引 |
int | length() 返回长度(字符数)。 |
char | charAt(int index) 返回 char在指定索引处字符值 |
StringBuilder | append(Object o) 将参数的字符串表示追加到序列中 |
StringBuilder | delete(int start, int end) 删除此序列的子字符串中的字符 |
StringBuilder | deleteCharAt(int index) 删除 char在这个序列中的指定位置 |
StringBuilder | insert(int offset, Object o) 将参数的字符串表示插入到此序列中指定的位置。 |
StringBuilder | reverse() 导致该字符序列被序列的相反代替 |
StringBuilder | replace(int start, int end, String str) 用指定的String中的字符替换此序列的子字符串中的 String |
String | substring(int start) 返回一个新的 String ,其中包含此字符序列中当前包含的字符的子序列 |
String | substring(int start, int end) 返回一个新的 String ,其中包含此序列中当前包含的字符的子序列 |
String | toString() 返回表示此顺序中的数据的字符串 |
注意:(1)StringBuilder容量扩展规则==当前容量*2+2
(2)end处的位置不包含
(3)注意StringBuilder方法的返回值类型,接收类型别搞错;另外返回值类型是StringBuilder,意味着之前的值已经被改变。
例:
public class StringBuilderTest2 {
public static void main(String[] args) {
StringBuilder str1=new StringBuilder();
//append(Object o) 将参数的字符串表示追加到序列中。
System.out.println(str1.append("hello"));//hello
//capacity() 返回当前容量
System.out.println(str1.capacity());//16
//StringBuilder容量扩展规则==当前容量*2+2,超过16按规则处理
StringBuilder str2=new StringBuilder();
str2.append("hahhojdppmlkjpjwoh");
System.out.println(str2.capacity());//34
//charAt(int index) 返回 char在指定索引处字符值。
System.out.println(str1.charAt(1));//e
//delete(int start, int end) 删除此序列的子字符串中的字符,end要注意是删到指定位置前面,end位置不包含
System.out.println(str1.delete(1, 3));//hlo
//deleteCharAt(int index) 删除 char在这个序列中的指定位置
System.out.println(str1.deleteCharAt(2));//hl
str1.append("wohenhao");
System.out.println(str1);//hlwohenhao
//indexOf(String str) 返回指定子字符串第一次出现的字符串的索引。
System.out.println(str1.indexOf("e"));//5
System.out.println(str1.lastIndexOf("h"));//7
//insert(int offset, Object o) 将参数的字符串表示插入到此序列中指定的位置。
System.out.println(str1.insert(1,"ss"));//hsslwohenhao
//length() 返回长度(字符数)
System.out.println(str1.length());//12
//reverse() 导致该字符序列被序列的相反代替。
System.out.println(str1.reverse());//oahnehowlssh
//replace(int start, int end, String str) 用指定的String中的字符替换此序列的子字符串中的 String 。
//同理这个end位置不包含
System.out.println(str1.replace(1, 4, "ii"));//oiiehowlssh
//substring(int start) 返回一个新的 String ,其中包含此字符序列中当前包含的字符的子序列。
System.out.println(str1.substring(2));//iehowlssh
//substring(int start, int end) 返回一个新的 String ,其中包含此序列中当前包含的字符的子序列。
System.out.println(str1.substring(2,6));//ieho
System.out.println(str1.substring(4,7));//how
//toString() 返回表示此顺序中的数据的字符串。
str1.toString();
System.out.println(str1.toString());
}
}
7.1.4 StringBuilder与String转换
(1)StringBuilder转String:StringBuilder的toString();
String的构造方法String(StringBuilder builder)
(2)String转StringBuilder:StringBuilder的构造方法
7.2 StringBuffer
StringBuffer类与StringBuilder类相似
7.2.1StringBuffer构造方法
- StringBuffer() 构造一个初始容量为16个字符的空StringBuffer对象;
- StringBuffer(CharSequence seq) 通过其他的StringBuffer对象创建一个新的StringBuffer对象;
- StringBuffer(int capacity) 构造一个由 capacity参数指定的初始容量得空StringBuffer对象;
- StringBuffer(String str) 构造一个初始化为指定字符串内容的StringBuffer对象。
7.2.2StringBuffer实例方法
- StringBuffer append(Object o) 将参数的字符串表示追加到序列中。
- int capacity() 返回当前容量。
- char charAt(int index) 返回 char在指定索引在这个字符值。
- StringBuffer delete(int start, int end) 删除此序列的子字符串中的字符。
- StringBuffer deleteCharAt(int index) 删除 char在这个序列中的指定位置。
- int indexOf(String str) 返回指定子字符串第一次出现的字符串内的索引。
- int lastIndexOf(String str) 返回指定子字符串最右边出现的字符串内的索引。
- StringBuffer insert(int offset, Object o) 将参数的字符串表示插入到此序列中指定的位置。
- int length() 返回长度(字符数)。
- StringBuffer reverse() 导致该字符序列被序列的相反代替。
- StringBuffer replace(int start, int end, String str) 用指定的String中的字符替换此序列的子字符串中的 String 。
- String substring(int start) 返回一个新的 String ,其中包含此字符序列中当前包含的字符的子序列。
- String substring(int start, int end) 返回一个新的 String ,其中包含此序列中当前包含的字符的子序列。
- String toString() 返回表示此顺序中的数据的字符串。
7.2.3 StringBuffer与String转换
(1)StringBuffer转String:StringBuffer的toString();
String的构造方法String(StringBuffer builder)
(2)String转StringBuffer:StringBufferr的构造方法
例:
public class StringBufferTest {
public static void main(String[] args) {
StringBuffer str1=new StringBuffer();
System.out.println("没有append之前的初始容量=="+str1.capacity());
str1.append("hello");
str1.append(1234);
str1.append(true);
str1.append(12.5);
str1.append("world");
System.out.println("str1=="+str1);
System.out.println("append之后的容量=="+str1.capacity());
System.out.println("StringBuilder容量扩展规则==当前容量*2+2");
System.out.println("charAt(3)=="+str1.charAt(3));
System.out.println("delete(13,17)=="+str1.delete(13,17));
System.out.println("deleteCharAt(3)=="+str1.deleteCharAt(3));
System.out.println("indexOf('l')=="+str1.indexOf("l"));
System.out.println("lastIndexOf('l')=="+str1.lastIndexOf("l"));
System.out.println("insert(12,12.5)=="+str1.insert(12,12.5));
System.out.println("length=="+str1.length());
System.out.println("replace(8,12,'false')=="+str1.replace(8,12,"false"));
//System.out.println("reverse()=="+str1.reverse());
System.out.println("substring(4, 8) =="+str1.substring(4, 8));
}
}
7.3 StringBuilder与StringBuffer的区别
- StringBuilder--一个可变的字符序列,不保证线程同步【线程安全】. 访问速度快 jdk1.5
- StringBuffer---一个可变的字符序列,保证线程安全. 访问速度慢 JDK1.0
7.4 String与StringBuilder/StringBuffer的区别
String | StringBuilder | StringBuffer | |
可变与否 | 不可变 | 可变 | 可变 |
线程安全与否 | 非线程安全 | 非线程安全 | 线程安全 |
运行速度 | 慢 | 快 | 较快 |
操作情况 | 少量的字符串操作 | 单线程下字符大量操作 | 多线程下字符串大量操作 |