目录
基本语法
- String类是用来保存字符串常量的类,具有内容不变性
- 格式
- String str = “hello”;
- String str = new String(“hello”);
- String类细节
- String类有很多的构造器(重载),常用的有String(String s)、String(char[] a)、String(char[] a,int startIndex,int count)、String(byte[] b)(这个构造器常用于网络编程)
- String类实现了两个重要的接口
- Serializable:String可以串行化,可以在网络传输
- Comparable:String对象可以相互比较大小
- String的内容具有不变性
- String类由final关键字修饰,表示该类不能被其他类所继承
- String类中的一个 char[] value 数组由final关键字修饰,表示该数组的地址不可被修改。
详解equals与"=="
- equals与"=="均为比较,其中equals比较的是两个字符串内容是否相同。 " == “比较的是两个字符串的"值”,即两个字符串的地址。
- 首先我们需要理解String类对象创建的底层机制。String类存放的字符串常量来自堆中的常量池,常量池的本质是一个哈希表。
-
当创建一个对象时,例如:String a = “Hello”,底层会先在常量池中寻找是否存在"Hello"这个字符串常量,如果存在,就在栈中创建一个对象引用指向常量池中该字符串常量,如果不存在就现在常量池中创建"Hello"常量,然后再在栈中创建一个对象引用指向常量池中该字符串常量。
-
当用String b = new String(“Hello”)创建一个对象时,首先依旧会在堆中的常量池中寻找是否有"Hello"常量,然后在堆中创建一个新的对象指向常量池中的”Hello“字符串常量.然后再在栈中创建对象引用指向堆中创建的对象
-
- 因此当用equals比较String类对象a和b时结果为true;用"=="比较String对象a和b时结果为false
String a = "Hello";
String b = new String("Hello");
a==b; //false
a.equals(b); //true
String类常用方法
equals //区分大小写,判断内容是否相等
equalslgnoreCase //忽略大小写,判断内容是否相等
length //获取字符串的长度
indexOf //获取字符(字符串)在字符串中第1次出现的索引,索引从0开始,找不到就返回-1
lastIndexOf //获取字符(字符串)在字符串中最后1次出现的索引,索引从0开始,找不到返回-1
substring //截取指定范围的字串
substring(n) //从索引n处开始取之后的所有字符
substring(n1,n2) //从索引n1处开始截取到n2-1的位置
trim //去前后空格
charAt //获取某索引处的字符,注意不能使用Str[index]这种方式
toUpperCase //转换成大写
toLowerCase //转换成小写
contact //拼接字符串
s.contact(“hhh”).contact(“hhh”).contact(heiheihei)
replace //替换字符串
s1 =s .replace(“aa”,“bbb”);将字符串中的aa全部转换成bbb
s.replace方法对s字符串不作影响
split //以某种字符为标志将字符串进行分割
s.split(’,’);//以’,'为分割将字符串分成若干个字串
toCharArray //将字符串转换成字符数组
compareTo //比较两个字符串大小,当两个字符串长度相等时,返回第一个不相等字符的差(前者-后者)
//字符串不相等时,如果在较小字符串中能够找到不相等的字符与前者一样,如果已有的字符全部相等则返回两个字符串长度的差(前者-后者)
format //格式化字符串
format的内容和c语言的printf语句内容相同
public class TestDemo {
public static void main(String[] args) {
//把字符数组转为字符串
char[] chars = {'a','b','c'};
String s = new String(chars);
System.out.println(s);
String s1 = new String(chars,1,2);
System.out.println(s1);
String s2 = "hello";
//获取字符串中的某个单个字符
System.out.println(s2.charAt(1)); //e
//将字符串转为字符数组
char[] chars1 = s2.toCharArray();
System.out.println(Arrays.toString(chars1)); //hello
//字节数组转为字符串
byte[] bytes = {1,2,3,4};
String s3 = new String(bytes,1,2);
//字符串转为字节
String s4 = "qiuruixiang";
byte[] bytes1 = s4.getBytes();
}
@Test
public void test(){
//字符串比较大小
String s1 = "hello";
String s2 = "hell";
//比较两个字符串内容是否相等
System.out.println(s1.equals(s2)); //false
//忽略大小写比较两个字符串内容是否相等
System.out.println(s1.equalsIgnoreCase(s2)); //false
//比较两个字符串的大小
//compareTo方法:
// 1.两个字符串长度相等,返回第一个对应位置字符不相同的ASCll码的差值
// 2.两个字符串长度不相等,首先比较都有字符的位置是否存在差异,存在就返回1的结果,如果都相同
// 则返回字符串长度的差值
System.out.println(s1.compareTo(s2)); //1
}
@Test
public void test1(){
//字符串查找
String s1 = "hello";
String s2 ="he";
//查找s1中是否有子串s2,返回布尔值
System.out.println(s1.contains(s2)); //true
//从s1指定位置查找s1中是否有子串s2,存在就返回对应索引值,否则返回-1
//原理是KMP算法
System.out.println(s1.indexOf(s2,2)); //false
//从倒数某个位置开始查找
System.out.println(s1.lastIndexOf(s2,2)); //true
//从母串指定位置判断是否以某个子串开始,返回布尔值
System.out.println(s1.startsWith(s2,1));
//判断母串是否以某个子串结束,返回布尔值
System.out.println(s1.endsWith(s2));
}
@Test
public void test2(){
//字符串替换
String s1 = "aaabadasd";
//将原串中的某个字符全部换为另外一个字符
// 注意!:replace的结果会new一个新的String对象,不会改变原串
String s2 = s1.replace('a','q'); //qqqbqdqsd
System.out.println(s1);
System.out.println(s2);
//将原串中的某个子串全部替换为另外一个字符串(字符串长度不要求)
String s3 = s1.replaceAll("ab","qiu"); //aaqiuadasd
System.out.println(s3);
//将原串中的第一个确定的子串替换为另外一个字符串(字符串长度不要求)
String s4 = s1.replaceFirst("aa","qiu"); //aaqiuadasd
System.out.println(s4);
}
@Test
public void test3(){
//字符串分割
String s1 = "qiuruixiang=10";
String[] s = s1.split("=");
for(String s2:s) {
//limit负责控制分割的最多份数
String[] s3 = s2.split("rui",2);
for(String s4:s3){
System.out.println(s4); //qiu xiang
}
System.out.println(s2); // qiuruixiang 10
}
//注意:当分割符号为|,*,.时,不能直接使用这些字符,要用转义字符"\\"来修饰
//注意:用\来分割时,字符串要写成:192\\168\\1\\1,split中要写成("\\\\"),因为\会和"结合
//如果1个字符串有多个分隔符,要用|连接
String s2 = "qiu:rui&xiang";
String[] strings = s2.split("&|:");
for(String s3:strings){
System.out.println(s3); //qiu rui xiang
}
}
@Test
public void test4(){
//字符串的截取
String s = "hello~world";
//从s的下标2开始截取子串
String sub = s.substring(2); //llo~world
//如果下标为0,不会创建新对象!
System.out.println(s.equals(s.substring(0))); //hello~world
//返回s指定的字符串(左闭右开)
String sub1 = s.substring(2,4); //ll
}
@Test
public void test5(){
//字符串转换
//去除一个字符串首尾所有空格,保留中间空格
String s = " ab cd ";
String s1 = s.trim(); //ab cd
System.out.println(s1);
System.out.println("==========");
//把字符串中的小写字母转为大写字母
String s2 = "abcABC11";
String s3 = s2.toUpperCase(); //ABCABC11
System.out.println(s3);
//把字符串中的大写字母转为小写字母
String s4 = s2.toLowerCase(); //abcabc11
System.out.println(s4);
//字符串拼接,拼接好的字符串不入池,'+'连接的常量字符入池
String s5 = "hello";
String s6 = "bit";
System.out.println(s5.concat(s6)); //hellobit
}
@Test
@SuppressWarnings("all")
public void test6(){
String a = new String("hello");
String b = "hello";
String c = "he" + "llo";
String buf = "he";
String d = buf + "llo";
String e = "he".concat("llo");
System.out.println(c == e); //false
System.out.println(a==b); //false
System.out.println(a==c);//false
System.out.println(b==c);//true
System.out.println(d==c);//false
System.out.println(d==a);//false
}
}
StringBuffer和StringBuilder
StringBuffer
-
基本介绍:java.lang.StringBuffer代表可变的字符序列,可以对字符串内容进行增删,很多方法与String相同,但StringBuffer是可变长度的
-
StringBuffer是一个容器
-
StringBuffer细节
- StringBuffer的直接父类是AbstractStringBuffer
- StringBuffer实现了Serializable接口,即StringBuffer对象可以串行化
- 在它的父类AbstractStringBuffer中有一个char[] value属性(没有final修饰),该value数组存放字符串内容,内容不是在常量池中而是在堆中
- StringBuffer是一个final类,不可以被继承
-
StringBuffer常用构造器
- StringBuffer() : 创建一个大小为16的char[]用于存放字符内容
- StringBuffer(10) : 在默认char[]长度为16的基础上再加上10
-
String和StringBuffer的相互转换
/*String转换成StringBuffer */ String str = "hello"; StringBuffer stringbuffer = new StringBuffer(str); //调用StringBuffer构造器 new StringBuffer().append(str); //调用append方法
/* StringBuffer转换成String*/ StringBuffer stringbuffer1 = new StringBuffer("jack"); String str1 = stringbuffer1.toString(); //调用toString方法 String str2 = new String(stringbuffer1); //调用String构造器
-
StringBuffer的常用方法
append(String对象) //在原先的基础上在其之后添加新的String构成新的StringBuffer
stringbuffer.append(“hello”);
delete(n1,n2) //删除n1~n2的字符[n1,n2);
replace(n1,n2,str) //将n1~n2的字符修改成str[n1,n2)
indexOf(str) //查找指定的str在字符串第一次出现的索引,找不到返回-1
insert(n1,str) //在索引为n1处插入str,原先为n1之后的内容自动后移
length //返回StringBuffer的长度
StringBuilder
-
基本介绍:
- 此类被设计用作StringBuffer的一个简易替换,用在字符串缓冲区被单个线程使用。单线程时优先使用该类(而不是StringBuffer)
- StringBuilder上主要操作是append和insert方法,可重载这些方法以接受任意类型数据
-
细节
直接父类与StringBuffer一样是AbstractStringBuilder
实现了Serializable:可以串行化(可以网络传输和保存到文件)
StringBuilder类由final关键字修饰,不可被继承
其字符序列与StringBuffer一样存放在其直接父类AbstractStringBuilder类的char[] value数组中(无final)
方法没有做互斥处理(synchronized关键字),因此在单线程下使用
String、StringBuffer、StringBuilder的比较
- StringBuilder和StringBuffer非常类似,均代表可变字符序列,方法也一样
- String:不可变字符序列,效率低但复用性高
- StringBuffer:可变字符序列,效率较高,多线程
- StringBuilder:可变字符序列,效率最高,单线程
- 对String类做大量修改时不要用String类,转成StringBuilder类再转换回String