文章目录
String类的概述
- 字符串是由多个字符组成的一串数据(字符序列),我们可以将它看为字符数组;
- 查看JDK提供的API,我们可以发现有这样两句话:
1、字符串字面值"abc"也可以作为此类的一个实现;
2、字符串是常量,一旦被创建,就不能被改变;
怎么理解给出的这两句话,看代码:
案例1:
---也就是说它可以作为字符串对象
public class MyTest3 {
public static void main(String[] args) {
System.out.println("abc".length());//3
}
}
案例2:
public class MyTest {
public static void main(String[] args) {
String s1 = "Hello";
String s2 = "Hello";
String s3 = "Hel" + "lo";
String s4 = "Hel" + new String("lo");
String s5 = new String("Hello");
String s6 = "H";
String s7 = "ello";
String s8 = s6 + s7;
System.out.println(s1 == s2); // true
System.out.println(s1 == s3); // true
System.out.println(s1 == s4); // false
System.out.println(s1 == s8); // false
System.out.println(s4 == s5); // false
}
}
【分析】
1、s1在创建对象的同时,在字符串池中也创建了其对象的引用。
2、由于s2也是利用字面量创建,所以会先去字符串池中寻找是否有相等的字符串,显然s1已经帮它创建好了,它可以直接使用其引用。那么s1和s2所指向的都是同一个地址,所以s1==s2
。
3、s3是一个字符串拼接操作,参与拼接的部分都是字面量,编译器会进行优化,在编译时s3就变成"Hello"了,所以s1==s3
。
4、s4虽然也是拼接,但“lo”是通过new关键字创建的,在编译期无法知道它的地址,所以不能像s3一样优化。所以必须要等到运行时才能确定,必然新对象的地址和前面的不同。
5、同理,s8由两个变量拼接,编译期也不知道他们的具体位置,不会做出优化。
6、s5是new出来的,在堆中的地址肯定和s4不同。
7、s6利用intern()方法得到了s5在字符串池的引用,并不是s5本身的地址。由于它们在字符串池的引用都指向同一个"Hello"对象,自然s1==s6
。
【总结】
1、字符串一旦被创建,就不能被改变,指的是这个值不能被改变,你改变的无非是这个栈内存字符串的指向;
2、字面量创建字符串会先在字符串池中找,看是否有相等的对象,没有的话就在堆中创建,把地址驻留在字符串池;有的话则直接用池中的引用,避免重复创建对象。
3、new关键字创建时,前面的操作和字面量创建一样,只不过最后在运行时会创建一个新对象,变量所引用的都是这个新对象的地址。
Java中的String类为什么不可变?
String有两种赋值方式:
1、通过"字面量"赋值。
String str = "Hello";
2、通过new关键字创建新对象。
String str = new String("Hello");
String类的方法
1、String类的构造方法
1、将字节数组——>字符串
2、将字符数组——>字符串
public String():空构造
public String(byte[] bytes):把字节数组转成字符串
public String(byte[] bytes,int index,int length):把字节数组的一部分转成字符串(index:表示的是从第几个索引开始, length表示的是长度)
public String(char[] value):把字符数组转成字符串
public String(char[] value,int index,int count):把字符数组的一部分转成字符串
public String(String original):把字符串常量值转成字符串
public class MyTest {
public static void main(String[] args) {
String s1 = new String();
//空串也是字符串
byte[] b = new byte[]{100, 101, 102, 103};
String s2 = new String(b);
//把字节数组的一部分转换成字符串,注意角标越界
String s3 = new String(b, 0, 2);
char[] c = {'a', 'b', 'c'};
String s4 = new String(c);
//同样注意角标越界
String s5 = new String(c, 0, 2);
String s6 = new String("我爱祖国");
int i=s3.length();
System.out.println(s1.toString());
System.out.println(s2);
System.out.println(s3);
System.out.println(s4.toString());
System.out.println(s5.toString());
System.out.println(s6.toString());
System.out.println(i);
}
}
输出结果为:
defg
de
abc
ab
我爱祖国
字符串s3的长度为:2
2、String类的判断功能
public boolean equals(Object obj): 比较字符串的内容是否相同,区分大小写
public boolean equalsIgnoreCase(String str): 比较字符串的内容是否相同,忽略大小写
public boolean contains(String str):判断字符串中是否包含传递进来的字符串
public boolean startsWith(String str):判断字符串是否以传递进来的字符串开头
public boolean endsWith(String str):判断字符串是否以传递进来的字符串结尾
public boolean isEmpty():判断字符串的内容是否为空串" "
public class MyTest3 {
public static void main(String[] args) {
String s1="HELLO";
String s2=new String("HELLO");
String s3=new String("hello");
String s4="";
System.out.println(s1.equals(s2));//true
System.out.println(s1.equalsIgnoreCase(s3));//true
System.out.println(s1.contains("LLO"));//true
System.out.println(s1.startsWith("HEL"));//true
System.out.println(s1.endsWith("LLO"));//true
System.out.println(s1.isEmpty());//false
System.out.println(s4.isEmpty());//true
}
}
- 关于
==
和 equlas() 的区别
public class MyTest3 {
public static void main(String[] args) {
String s1 = new String("hello");
String s2 = new String("hello");
System.out.println(s1 == s2);//false
System.out.println(s1.equals(s2));//true
String s3 = new String("hello");
String s4 = "hello";
System.out.println(s3 == s4);//false
System.out.println(s3.equals(s4));//true
String s5 = "hello";
String s6 = "hello";
System.out.println(s5 == s6);//true
System.out.println(s5.equals(s6));//true
}
}
==号判断的是两个字符串的地址值是否相同,而 equals() 判断的是两个字符串的值是否相同,String类重写了这个方法;
//案例演示: 需求:模拟登录,给三次机会,并提示还有几次。
public static void main(String[] args)
{
//案例演示: 需求:模拟登录,给三次机会,并提示还有几次。
Scanner sc=new Scanner(System.in);
int count=1;
while(count<=3)
{
System.out.println("请输入用户名:");
String name=sc.nextLine();
System.out.println("请输入密码:");
String pwd=sc.nextLine();
//注意:不能使用==号比较,否则就是比较地址值
if(name.equals("admin")&&pwd.equals("888888"))
{
System.out.println("登录成功");
break;
}
else
{
System.out.println("用户名或密码输入错误,你还有"+(3-count)+"次机会");
count++;
}
}
}
3、String类的获取功能
public int length(): 获取字符串的长度。
public char charAt(int index): 获取指定索引位置的字符
public int indexOf(int ch): 返回指定字符在此字符串中第一次出现处的索引。
public int indexOf(String str): 返回指定字符串在此字符串中第一次出现处的索引。
public int indexOf(int ch,int fromIndex):返回指定字符在此字符串中从指定位置后第一次出现处的索引。
public int indexOf(String str,int fromIndex): 返回指定字符串在此字符串中从指定位置后第一次出现处的索引。
public String substring(int start): 从指定位置开始截取字符串,默认到末尾。
public String substring(int start,int end): 从指定位置开始到指定位置结束截取字符串。
public class MyTest4 {
public static void main(String[] args) {
String s1="我爱祖国";
System.out.println(s1.length());//获取字符串的长度
char c=s1.charAt(1);//根据索引获取字符,注意不要超出范围
System.out.println(c);
int i=s1.indexOf('爱');//根据字符获取索引,如果没有找到则返回 -1
System.out.println(i);
int j=s1.indexOf("祖国");//根据字符串获取索引
System.out.println(j);
String s2="abcdefghabcijklmnabc";
int a = s2.indexOf('a', 3);
//根据给定的字符查找字符串中给定索引开始第一次出现的该字符的位置
System.out.println(a);
int b=s2.indexOf("abc",4);
//根据给定的子字符串查找字符串中给定索引开始第一次出现的该字符的位置
System.out.println(b);
String s3 = s2.substring(7);//根据给定索引开始截取字符串至结束
System.out.println(s3);
String s4=s2.substring(4,7);//根据给定范围截取字符串,含头不含尾
System.out.println(s4);
}
}
//输出结果为:
4
爱
1
2
8
8
habcijklmnabc
efg
public class MyTest3 {
public static void main(String[] args) {
/*案例演示:
需求:统计一个字符串中大写字母字符,小写字母字符,数字字符出现的次数。(不考虑其他字符)*/
String str="asdfassASFSsd00214fsddf1441asdfasdf88asdfdfAFA";
//遍历字符串,获取每一个字符,怎么判断这个字符,是什么样的字符
int xiao=0;
int da=0;
int num=0;
for (int i = 0; i < str.length(); i++) {
char ch = str.charAt(i);
//根据ASCII码表去判断
if(ch>='a'&&ch<='z')
xiao++;
else if(ch >= 'A' && ch <= 'Z')
da++;
else if(ch >= '0' && ch <= '9')
num++;
}
System.out.println("大写字母"+da);
System.out.println("小写字母" + xiao);
System.out.println("数字字符" + num);
}
}
//输出结果:
大写字母7
小写字母28
数字字符11
4、String类的转换功能
public byte[] getBytes(): 把字符串转换为字节数组
public char[] toCharArray(): 把字符串转换为字符数组
public static String valueOf(char[] chs): 把字符数组转成字符串
public static String valueOf(int i): 把int类型的数据转成字符串
注意:String类的valueOf方法可以把任意类型的数据转成字符串;
public String toLowerCase(): 把字符串转成小写
public String toUpperCase(): 把字符串转成大写
public String concat(String str): 把字符串拼接
public class Mytest5 {
public static void main(String[] args) {
byte[] bytes = "abcdef".getBytes();
for (int i = 0; i < bytes.length; i++) {
System.out.println(bytes[i]);
}
String s2 = "abcd";
char[] c = s2.toCharArray();
for (int i = 0; i < s2.length(); i++) {
System.out.println(c[i]);
}
char[] c1 = {'a', 'b', 'c', 'd', 'e'};
String s3 = String.valueOf(c1);
System.out.println(s3);
String s4 = String.valueOf(123);
System.out.println(s4);
String s5="ADFGHJKL";
System.out.println(s5.toLowerCase());
String s6="asdfghj";
System.out.println(s6.toUpperCase());
System.out.println(s5.concat(s6));
}
}
//输出结果:
97
98
99
100
101
102
a
b
c
d
abcde
123
adfghjkl
ASDFGHJ
ADFGHJKLasdfghj
public class Mytest5 {
public static void main(String[] args) {
//把一个字符串的首字母转成大写,其余为小写
String s="abdchGTFD";
char c=s.charAt(0);
String newStr=String.valueOf(s.charAt(0)).toUpperCase().concat(s.substring(1));
System.out.println(newStr);
}
}
//输出结果为:
AbdchGTFD
5、String类的其他功能
public String replace(char old,char new) 将指定字符进行互换
public String replace(String old,String new) 将指定字符串进行互换
public String trim() 去除两端空格
public int compareTo(String str)
按照字典顺序比较,会对照ASCII 码表从第一个字母进行减法运算,返回的就是这个减法的结果
如果前面几个字母一样会根据两个字符串的长度进行减法运算返回的就是这个减法的结果;
如果连个字符串一摸一样 返回的就是0;
public int compareToIgnoreCase(String str) 忽略大小写的比较 ,和上面一样
public class Mytest5 {
public static void main(String[] args) {
String s1="abcdef".replace('b','*');
System.out.println(s1);
String s2="我爱祖国".replaceAll("爱","##");
System.out.println(s2);
String s3=" 2333456888fff ".trim();
System.out.println(s3);
int i="ABCDEF".compareTo("ABCDEI");
System.out.println(i);
int j="ABCDEF".compareToIgnoreCase("abcdef");
System.out.println(j);
}
}
//输出结果为:
a*cdef
我##祖国
2333456888fff
-3
0
关于String类的习题
public class MyTest6 {
public static void main(String[] args) {
//举例:int[] arr = {1,2,3}; 拼接结果:"[1, 2, 3]"
int[] arr = {1,2,3};
//定义一个字符串
String str="[";
for (int i = 0; i < arr.length; i++) {
if(i==arr.length-1){
str+=arr[i]+"]";
}else{
str += arr[i]+",";
}
}
System.out.println(str);
}
}
输出:[1, 2, 3]
public class MyTest6 {
public static void main(String[] args) {
//1.去掉字符串的中间空格
String str1= "a b d e fa faf";
char[] c=str1.toCharArray();
String newStr1="";
for (int i = 0; i < c.length; i++)
{
if(c[i]!=' ')
newStr1+=String.valueOf(c[i]);
}
System.out.println("新的字符串为:"+newStr1);
//2.去掉字符串的左端空格
String str2 = " a b d e fa faf ";
char[] c1=str2.toCharArray();
String newStr2="";
int i=0;
while(i<c1.length)
{
if(c1[i]!=' ')
break;
i++;
}
newStr2=str2.substring(i);
System.out.println("新的字符串为:"+newStr2);
//3.去掉字符串的右端空格
String str3 = " a b d e fa faf ";
char[] c2=str3.toCharArray();
String newStr3="";
for (int j = c2.length-1; j >= 0; j--)
{
if(c2[j]!=' ')
{
newStr3=str3.substring(0,j+1);
break;
}
}
System.out.println("新的字符串为:"+newStr3);
}
}
//输出结果为:
新的字符串为:abdefafaf
新的字符串为:a b d e fa faf
新的字符串为: a b d e fa faf
public class MyTest6 {
public static void main(String[] args) {
//统计大串中小串出现的次数
String str="woaijavawozhenaijavawozhendeaijavawozhendehenaijavaxinbuxinwoaijavagun";
str=str.replace("java","*");
char[] arr=str.toCharArray();
int i=0,count=0;
for (int j = 0; j < arr.length; j++)
{
if(arr[j]=='*')
count++;
}
System.out.println("java在字符串中出现了"+count+"次");
}
}
//输出结果为:
java在字符串中出现了5次
StringBuffer类的概述
我们如果对字符串进行拼接操作,每次拼接都会构建一个新的String对象或者使用+号,既耗时又浪费空间。而StringBuffer就可以解决这个问题,它是线程安全的可变字符序列,在大量拼接字符串时,就可以使用长度可变的字符容器,构造一个其中不带字符的字符串缓冲区,初始容量为 16 个字符;
StringBuffer的构造方法:
public StringBuffer(): 无参构造方法
public StringBuffer(int capacity): 指定容量的字符串缓冲区对象
public StringBuffer(String str): 指定字符串内容的字符串缓冲区对象
StringBuffer的成员方法:
public int capacity():返回当前容量——理论值
public int length():返回长度(字符数)——实际值
StringBuffer的添加功能:
public StringBuffer append(String str):可以把任意类型数据添加到字符串缓冲区里面,并返回字符串缓冲区本身
public StringBuffer insert(int offset,String str):在指定位置把任意类型的数据插入到字符串缓冲区里面,并返回字符串缓冲区本身
StringBuffer的删除功能:
public StringBuffer deleteCharAt(int index):删除指定位置的字符,并返回本身
public StringBuffer delete(int start,int end):删除从指定位置开始指定位置结束的内容,并返回本身
StringBuffer的替换功能:
public StringBuffer replace(int start,int end,String str): 从start开始到end用str替换
StringBuffer的反转功能:
public StringBuffer reverse()
StringBuffer的截取功能:
public String substring(int start): 从指定位置截取到末尾
public String substring(int start,int end): 截取从指定位置开始到结束位置,包括开始位置,不包括结束位置,
注意事项:返回值类型不再是StringBuffer本身
public class MyTest1 {
public static void main(String[] args) {
StringBuffer s1=new StringBuffer(5);
s1.append("1234567");
System.out.println(s1.capacity());
System.out.println(s1.length());
StringBuffer s2=new StringBuffer();
System.out.println(s2.capacity());
s2.capacity();
System.out.println(s2.capacity()==s2.length());
StringBuffer s3=new StringBuffer("好好学习");
System.out.println(s3);
s3.insert(1,"学习");
System.out.println(s3);
System.out.println(s3.deleteCharAt(2));
System.out.println(s3.delete(0, 1));
System.out.println(s3.replace(0, 2, "天天向上"));
System.out.println(s3.reverse());
System.out.println(s3.substring(0));
System.out.println(s3.substring(0, 2));
}
}
//输出结果为:
12
7
16
false
好好学习
好学习好学习
好学好学习
学好学习
天天向上学习
习学上向天天
习学上向天天
习学
StringBuffer和String的相互转换
public class MyTest1 {
public static void main(String[] args) {
//String--->StringBuffer
String str="我爱祖国";
StringBuffer s1=new StringBuffer(str);//1
System.out.println("s1是:"+s1);
StringBuffer s2=new StringBuffer().append(str);//2
System.out.println("s2是:"+s2);
//StringBuffer--->String
String newStr1=s1.toString();//1
System.out.println("newStr1是:"+newStr1);
String newStr2=s2.substring(0);//2
System.out.println("newStr2是:"+newStr2);
String newStr3=new String(s2);//3
System.out.println("newStr3是:"+newStr3);
}
}
输出结果都为:我爱祖国
StringBuffer和StringBuilder的区别
StringBuilder——适用于单线程下大量数据,效率高,线程非安全;
StringBuffer——适用于多线程下大量数据,效率低,线程安全;
String——适用于使用少量数据;
String和StringBuffer分别作为参数传递
String虽然是引用类型,但是它是一个常量,所以在做传递的时候,完全可以将其看成基本数据类型数据进行传递;
StringBuffer作为参数传递是引用类型传递;
public class MyTest {
public static void main(String[] args) {
String str="爱生活,爱Java";
test(str);
System.out.println(str); //爱生活,爱Java
StringBuffer sb = new StringBuffer("好好学习天天向上");
test(sb);
System.out.println(sb.toString());//上向天天习学好好
}
private static void test(StringBuffer sb) {
sb.reverse();
}
private static void test(String str) {
String substring = str.substring(2);
System.out.println(substring); //活,爱Java
}
}