前言
大家好呀,本期将要带大家认识一下Java中的String类,本期注意带大家认识一些String类常用方法,和区分StringBuffer和StringBuilder感谢大家收看
一,String对象构造方法与原理
String类为我们提供了非常多的重载的构造方法让我们构造字符对象,感兴趣可以点开源码看看,下面介绍常用四种以及使用场景
1.常量池直接构造:最简便的构造方式,栈中创建的对象的引用指向常量池中的对象,如下图str
2.使用new构造:在堆区中开辟一片空间存放字符对象,如下图str1
3.字符数组构造:New的String对象传入一个字符数组构造字符对象,如下图str2
4.字节数组构造:利用字节数组构造,此时需注意字节数组中存放字母的ACCII码值,构造时需选择编码格式,一般使用UTF-8编码格式进行编码如下图str3
public class Test {public static void main(String[] args) throws UnsupportedEncodingException {String str="helloWorld";//直接构造String str1=new String("helloWorld");//new出对象char[] ch={'h','e','l','l','o','W','o','r','l','d'};String str2=new String(ch);//字符数组构造byte[] bytes = {104, 101, 108, 108, 111}; // 字节数组,对应ASCII "hello"String str3 = new String(bytes, "UTF-8"); // 使用UTF-8编码构造字符串System.out.println(str+"\n"+str1+"\n"+str2+"\n"+str3);}
}
值得一提利用字符数组和字节数组有常见的构造方法
表示截取var1字数数组中从var2到var3的字符构造字符串,截取的区间左闭右闭,例如
二,String对象的不可变性
String对象一经创建,便不可更改,更改的话,只会在创建一个新的对象,把更改过后的内容放进去,这个就是String对象的不可变性,String的这个特性使的对String对象的操作相对低效,于是StringBuilder类就可以提高我们的效率。后面介绍StringBuilder类时会详细说明
三,String类中的常用方法
1,字符串转换
(1)大小写转换
java中使用toUpperCase和toLowercase对字符串进行大小写转换,注意这个方法不会改变原来字符串,而是返回一个新的字符串
public class Test1 {public static void main(String[] args) {String str="HELLO";String str1=str.toLowerCase();System.out.println(str1);String str2="hello";String str3=str2.toUpperCase();System.out.println(str3);}
}
(2)字符串和数值转换
Java中,如果想把一个子符转成数值需要用到它们对应类型的包装类,同样,把任意类型对象转成字符串需要用到String的valueOf方法,如下
public class Test1 {public static void main(String[] args) {String s="1234";System.out.println(Integer.parseInt(s));int i=1234;System.out.println(String.valueOf(i));}
}
(3)字符串转数组
字符串对象调用toCharArray方法,返回一个字符数组,可以得到字符串中每个字符,然后,我们可以遍历这个数组打印观察其中的字符
public class Test1 {public static void main(String[] args) {String str="hello";char[] ch=str.toCharArray();for (int i=0;i<ch.length;i++){System.out.println(ch[i]);}}
}
(4)格式化
String类调用format方法,优点在于可以更方便地创建复杂的输出字符串,特别是在需要格式化输出的时候,学过C语言的小伙伴们应该不陌生,例如
public class Test1 {public static void main(String[] args) {String str="hello";String str1="World";int i=10;System.out.println(String.format("%s %s %d", str, str1,i));}
}
2,寻找字符
(1)寻找某个下表对应字符--charAt
String对象调用charAt(in i)方法,传入一个字符串对应字符的下标,返回对应下标的字符,源码如下
顺带一提如果字符由数字组成也返回一个数字字符
public class Test1 {public static void main(String[] args) {String str="hello";String str1="World";String str3="16774";char ch=str3.charAt(1);char ch1=str1.charAt(0);System.out.println(ch);System.out.println(ch1);}
}
(2)寻找某个字符首次出现位置--indexOf
String对象调用Indexof方法传入一个字符,返回对应字符首次出现的下标值,它还可以在传入一个int值表示从这个int值对应的下表开始找对应字符,没找到返回-1。
public class Test1 {public static void main(String[] args) {String str="Hello World";System.out.println(str.indexOf("l"));System.out.println(str.indexOf("l",5));//只传入一个数,表示从5下标一直找到结尾}
}
(3)从字符串末尾开始向前找字符--lastIndexof
与indexof用法类似,不过这次是从后向前找字符,没找到则返回-1
public class Test1 {public static void main(String[] args) {String str="Hello World";System.out.println(str.lastIndexOf("l"));System.out.println(str.lastIndexOf("l",5));//传入一个数,表示从5一直向前找}
}
3,字符串比较
(1)==
实质上是比较字符串的地址,同一地址返回true否则返回false
public class Test1 {public static void main(String[] args) {String str="Hello";String str1=new String("Hello");String str2="Hello";String str3=new String("Hello");System.out.println(str==str1);//前面已经讲过字符串的构造,很明显地址不同System.out.println(str==str2);//都在常量池中地址相同System.out.println(str1==str3);//每次new都会在堆区开辟空间,二者地址不同}
}
(2)equals
只比较字符串内容,与地址无关(String内部重写了这个方法)
public class Test1 {public static void main(String[] args) {String str = "Hello";String str1 = new String("Hello");String str2 = "Hello";System.out.println(str.equals(str1));System.out.println(str.equals(str2));System.out.println(str1.equals(str2));}
}
(3)compareTo
这部分内容我们在接口部分讲过,主要是我们重写Comparable接口中的compareTo方法来比较两个字符类型的大小。注意String类是重写了compareTo这个方法的,我们直接使用即可,它会根据比较字符的大小返回一个整型值,对这部分内容感兴趣的朋友们可以看看CSDN这篇文章,下面说明String对象如何调用这个方法
public class Test {public static void main(String[] args) {String s="hello";String s1="world";System.out.println(s.compareTo(s1));//s小于s1,返回一个小于0的数System.out.println(s1.compareTo(s));//s1大于s,返回一个大于0的数System.out.println(s.compareTo(s));//相同字符串返回0}
}
4,字符串操作
(1)替换操作--replace
使用replace方法可以把字符串中特定的所有字符替换成指定字符
public class Test {public static void main(String[] args) {String s = "hello,world";String s1 = s.replace("l", "s");System.out.println(s+"\n"+s1);}
}
当然,这个方法会返回一个新对象,不会对原来字符串做任何修改
(2)分裂操作--split
Java中有将字符串根据指定字符拆分成几个子字符串的方法
由源码可以看出,这个方法传入一个字符,返回一个String类型的数组,我们可以通过遍历得到这个数组每个元素
public class Test {public static void main(String[] args) {String s = "hello,world";String[] str=s.split("l");for (int i = 0; i <str.length; i++) {System.out.println(str[i]);}}
}
当然也可以传入一个字符串
public class Test {public static void main(String[] args) {String s = "hello,world";String[] str=s.split("ll");for (int i = 0; i <str.length ; i++) {System.out.println(str[i]);}}
}
当然,要是没有这个字符那么这个字符串就不会被分割
public class Test {public static void main(String[] args) {String s = "hello,world";String[] str=s.split("k");for (int i = 0; i <str.length ; i++) {System.out.println(str[i]);}}
}
四,StringBuffer与StringBuilder应用与区分
StringBuffer与StringBuilder用法和功能都是类似的,区别就在于StringBuilder对字符串的操作都是在原字符之上修改,并不会创建新的对象,这就使得StringBuiler效率优于String类,举个例子,StringBuilder类有一个append的拼接字符串的方法,这个方法就会比String类通过+=拼接效率更高
import java.util.Timer;public class Test {public static void main(String[] args) {String s = "hello";StringBuilder s1 = new StringBuilder("hello");Long time1=System.currentTimeMillis();//记录当前时间for (int i = 0; i <10000 ; i++) {s+="i";}Long time2=System.currentTimeMillis();for (int i = 0; i < 10000; i++) {s1.append("i");}Long time3=System.currentTimeMillis();System.out.println(time2-time1);System.out.println(time3-time2);}
}
另外,StringBuilder对象可以通过toString方法转化成String对象
public class Test1 {public static void main(String[] args) {StringBuilder s1 = new StringBuilder("hello");String s=s1.toString();}
}
StringBuffer类于他们只有一个区别,StringBuffer类的操作属于线程安全操作,它的大部分方法都加上了
synchronized关键字,如下
线程安全操作简单理解就是指在多线程情况下,这个方法会被执行完才会让出cpu资源,执行后面代码,这保证了代码逻辑的正确性,当然,与之相对效率差一点点,所以在单线程情况下还是常用另外两个方法。
本期博客就到到这里啦,记录个人学习欢迎大家指正错误哦,谢谢大家,我们下期见