String字符串
String是一个类,属于数据类型中的引用类型。
Java的一切使用""引起来的内容,都是这个类的实例,称为字符串对象。
字符串在定义后,值不可改变,是一个常量,实际是一个数组。
String类使用时注意
由此可见,如果要频繁改动String类型变量的值,会创建很多字符串对象,效率很低
所以在频繁改动字符串时,不要使用String类。
如果要频繁改动字符串时,使用StringBuilder或StringBuffer类
如何创建字符串对象
1.使用""赋值创建
String str="abc";
2.通过构造方法创建
常用构造方法 | 说明 |
String() | 创建一个空白字符串对象 即" " |
Strint(String str) | 创建一个指定字符串对象 |
String(char[] list) | 创建一个指定字符数组的字符串对象 |
String(byte[] bytes,String charsetName) |
按指定的编码格式创建一个指定字节数组的字符串对象 |
不同方式创建字符串的过程
//这句话执行时,判断"ab"是否存在于字符串缓冲区中,不存在,创建,将其地址保存到str1中
String str1 = "ab";
//这句话执行时,判断"ab"是否存在于字符串缓冲区中,已存在,将其地址保存到str2中
String str2 = "ab";
//这句话执行时,+两端如果都是""定义的字符串,拼接后再判断"ab"是否存在于字符串缓冲区中,已存在,将其地址保存到str3中
String str3 = "a" + "b";
//以上三句话,只有一个字符串对象创建,即"ab",str1,str2,str3指向了同一个地址,所以用==比较都是true
System.out.println(str1 == str2);
System.out.println(str1 == str3);
可以使用JDK中自带的反编译工具javap对class文件进行反编译。
在
class
文件所在目录下
(
项目的
out
目录中
)
,进入控制台,输入
javap -c
字节码文件名
.class
使用构造方法String(String str)创建
//这句话的执行流程
//1.在字符串缓冲区中寻找"ab",不存在,创建
//2.在堆中new String()创建对象,将字符串缓冲区中的"ab"的字符串地址保存在new String()的区域中
//3.将堆中new String()整个对象保存到栈中str1变量中
String str1 = new String("ab");
//这句话的执行流程
//1.在字符串缓冲区中寻找"ab",存在
//2.在堆中new String()创建对象,将字符串缓冲区中的"ab"的字符串地址保存在new String()的区域中
//3.将堆中new String()整个对象保存到栈中str1变量中
String str2 = new String("ab");
//以上两句话,在字符串缓冲区中有一个"ab"的字符串,在堆中有两个对象
//str1和str2保存堆中不同的两个地址,所以为false
System.out.println(str1 == str2);
使用+拼接""和new出来的字符串对象创建
//在字符串缓冲区中创建"ab"
String str1 = "ab";
//1.创建StringBuilder对象
//2.在字符串缓冲区中创建"a"
//3.在字符串缓冲区中创建"b"
//4.在堆中new String(),将"b"保存在其中
//5.调用StringBuilder对象的append()方法,将"a"和new String("b")拼接
String str2 = "a" + new String("b");//一共会创建"a","b",new String(),new StringBuilder()四个对象
//两个不同的地址
System.out.println(str1==str2);
总结
在使用字符串时,字符串是对象,如果要比较其值是否相同,不能使用==判断,因为==判断的是内存地址。
所以在比较字符串是否相同时,要使用String类重写的equals方法进行判断。
String类中equals重写的原理大致是:判断是否为同一个字符串,再判断是否是字符串类型,再将两个字符串转换为字节数组,逐一比较字节数组中的内容,全部一致,返回true
调用equals方法时,通常将已知非空字符串作为调用者
username.equals("admin");//username可能为空,会有空指针异常
"admin".equals(username)//能避免空指针异常
字符串相关面试题
题目一
String str1="ab";//字符串缓冲区中创建"ab"
String str2="ab";//使用字符串缓冲区中的"ab"
String str3="a"+"b";//使用字符串缓冲区中的"ab"
String str4=new String("ab");//使用字符串缓冲区中的"ab",将其保存在new String()中 String str5="a"+new String("b");//创建"a"和"b",将"b"保存在new String(),将"a"和new String()保存在StringBuidler对象中
System.out.println(str1==str2);//true
System.out.println(str1==str3);//true
System.out.println(str1==str4);//false
System.out.println(str1==str5);//false
//题目二
String s1="abc";
String s2="a"+"b"+"c";
//以上两句话执行后会创建几个对象?一个"abc"
//题目三
String str=new String("hello");
//这句话执行时会创建几个对象?
//1个或2个
//如果字符串缓冲区中有"hello",只会创建new String(),这时只创建一个对象 //如果字符串缓冲区中没有"hello",会创建"hello"和new String(),这时会创建两个对象
//题目四
String s3=new String("wor");
//堆中new String() 常量池"wor" String s4=s3+"ld";
//堆中new StringBuilder() 常量池"ld" //以上两句话会创建几个对象?
//4个
//+两端都是""赋值的字符串,拼接发生在编译阶段,将最终拼接的结果保存在字符串缓冲区中 //其余情况都会创建StringBuilder拼接字符串
字符串String类中的常用方法
方法名 | 返回值 | 作用 |
length() | int | 得到字符串的长度 |
toLowerCase | String | 转换为小写 |
toUpperCase | String | 转换为大写 |
trim() | String | 去除字符串的首尾空格 |
isEmpty() | boolean | 判断字符串长度是否为0 |
getBytes() | byte[] | 转换为字节数组 |
toCharArray | char[] | 转换为字符数组 |
equalslgnoreCase(String str) | boolean | 忽略大写写比较字符串是否相同 |
equals(String str) | boolean | 判断两个字符串是否相等 |
charAt(int index) | char | 得到某个索引上的字符 |
indexOf(String str) | int | 得到某个字符串的第一次出现的索引,不存在返回-1 |
lastindexOf(String str) | int | 得到某个字符串最后一次出现的索引,不存在返回-1 |
contains(String str) | boolean | 判断是否存在某个字符串 |
startWith(String str) | boolean | 判断是否以指定字符串开头 |
endsWith(String str) | boolean | 判断是否以指定字符串结尾 |
concat(String str) | String | 将指定字符串拼接到源字符串末尾 |
substring(int index) | String | 从索引index开始截取字符串至末尾 |
substring(int begin,int end) | Strint | 截取[begin,end]范围内的字符串 |
split(String regex) | String[] | 根据字符串或正则表达式切分源字符串 |
replace(String oldStr,String newStr) | String | 将元字符中的oldStr替换为newStr |
String.valueOf(参数) | String | 将参数转换为字符串。参数可以是任何数据,通常用于原始类型转换为字符串 |
String.format(String 格式,Obiect...obj) | String | 根据指定格式转换参数,常用与将浮点数据保留指定小数位数。\n如String.format("%4.2f",2.345)表示将2.345保留2位小数,整体占4位,输出为字符串格式。如果时间数字总位数大于4,原样输出,如果实际数字总位数小于4,会在最前补充空格 |
可变字符串
String字符串对象是一个常量,在定义后值不可改变。
如果使用String类的对象,对其频繁更新时,就会不停的创建新对象,不停引用给同一个变量。
如果要执行10000次循环重写赋值的过程,就会创建10000个字符串对象,效率很低,这时就需要使用可变字符串对象。
public static void main(String[] args) {
System.out.println("程序开始执行");
String str="hhhh";
long startTime=System.currentTimeMillis();
StringBuilder sb=new StringBuilder("hhhh");
for (int i = 0; i < 500000; i++) {
sb.append(i);
}
long endTime=System.currentTimeMillis();
System.out.println("程序执行完毕");
System.out.println("用时"+(endTime - startTime) + "毫秒");
}
StringBuilder
用于表示可变字符串的一个类,是
非线程安全
的,在单线程环境下使用,效率更高。
StringBuffer
用于表示可变字符串的一个类,是
线程安全
的,在多线程环境下使用。
StringBuilder和
StringBuffer
中的方法都一致,只不过
StringBuffer
中的方法使用了
synchronized
关键字 修饰,表示是一个同步方法,在多线程环境下不会出现问题。
这里以StringBuilder为列
构造方法
常用构造方法 | 作用 |
StringBuilder()
|
创建一个大小为
16
的字节数组,表示一个空白字符串。
|
StringBuilder(int capacity)
|
创建一个指定大小的字节数组,表示一个空白字符串。
|
StringBuilder(String str)
|
创建一个
str
的长度
+16
大小的字节数组。表示
str
这个字符串。
|
常用方法
常用方法 | 作用 |
append(Object obj) | 将任意数据添加到原可变字符串末尾 |
delete(int start,int end) | 删除[start,end]范围内的字符 |
deleteCharAt[int index] | 删除index索引上的字符 |
insert(int index,Object obj) | 将obj添加到index上 |
replace(int start,int end,String str) |