string类基本概念string类属于引用数据类型,不属于基本数据类型。
在java中只要是 (双引号)中的,都是string对象。
java中规定,双引号中的字符串是不可变的,也就是说abc自出生到死亡都不可能变成abcd,也不能变成ab。
在jdk中双引号括起来的字符串都是存储在方法区的字符串常量池当中的。(因为在实际开发中,字符串的使用频率十分高,为了执行效率,就把字符串放在了方法区中的字符串常量池当中)
string字符串的存储原理通过 string s = “abc” 这种方式,会在方法区中的字符串常量池创建对象,s会保存该字符串在字符串常量池中的地址。
通过 string s = new string(“abc”)的方式创建对象,首先会在字符串常量池中创建abc对象(如果字符串常量池中已经有了abc则不会再次创建),然后会在堆区创建string类对象,它会储存 abc 在方法区中的地址,s又会保存堆中string对象的地址。
看以下代码:
public class stringtest01 { //这两行代码表示创建3个字符串对象,且都在字符串常量池中 string a = "abc"; string b = "abc" + "de"; //通过 new 来创建字符串对象,会先在字符串常量池中寻找"abc" //找不到的话就会在字符串常量池中创建一个"abc"对象 //在堆中创建创建字符串对象,并且保存"abc"在字符串常量池中的地址 string c = new string("abc");}
按照以上代码画出jvm内存简图如下:
知道了string类字符串的存储原理之后,就可以很容易知道以下代码的编译结果:
public class stringtest01 { public static void main(string[] args) { //没有在堆中创建对象 //s1与s2都存的是"hello"在字符串常量池中的地址 string s1 = "hello"; string s2 = "hello"; //在堆中创建了对象 //m,n分别存的是他们在堆中对象的地址 string m = new string("你好!"); string n = new string("你好!"); system.out.println(s1 == s2);//结果为true system.out.println(m == n);//结果为false }}
string类的常用构造方法//string类构造方法的使用public class stringtest02 { public static void main(string[] args) { byte []x1 = { 97 , 98 , 99 }; char []x2 = {'我','是','中','国','人'}; //string s = new string(byte数组); string y1 = new string(x1); system.out.println(y1);//abc //string s = new string(byte数组,偏移量,长度) string y2 = new string(x1,1,2); system.out.println(y2);//bc //string s = new string(char数组) string y3 = new string(x2); system.out.println(y3);//我是中国人 //string s = new string(char数组,偏移量,长度) string y4 = new string(x2,2,3); system.out.println(y4);//中国人 }}
string类中常用方法public class stringtest03 { public static void main(string[] args) { //public char charat(int index)方法 //返回索引值处的char类型字符 char s1 = "中国人".charat(1); system.out.println(s1);//国 //public int compareto(string anotherstring)方法 //按字典序比较两个字符串 system.out.println("abc".compareto("abd"));//负整数 system.out.println("abc".compareto("abc"));//0 system.out.println("abc".compareto("abb"));//正整数 //public boolean contains(charsequence s)方法 //判断字符串是否包含s system.out.println("abcdefg".contains("efg"));//true system.out.println("abcdefg".contains("hij"));//false //public boolean endswith(string suffix)方法 //判断字符串是否以suffix结尾 system.out.println("abcde".endswith("cde"));//true system.out.println("abcde".endswith("qwe"));//false //public boolean equalsignorecase(string anotherstring) 方法 //判断两个字符串是否相等,忽略大小写 system.out.println("abcd".equalsignorecase("abcd"));//true //public byte[] getbytes() //将字符串转换成byte数组,并返回 byte [] s2 = "abcdefg".getbytes(); for (int i = 0; i < s2.length; i++) { system.out.print(s2[i] + " "); }//97 98 99 100 101 102 103 //public int indexof(string str) //判断某个子字符串在当前字符串中第一次出现处的索引 //若子字符串不存在,返回-1 system.out.println("abcdefghigk".indexof("hig"));//7 system.out.println("abc".indexof("fgh"));//-1 //public int lastindexof(string str) //判断某个子字符串最后一次出现在当前字符串中的索引 system.out.println("abcdhdhdabc".lastindexof("abc"));//8 //public boolean isempty() //判断字符串是否为空串 //底层调用length()方法,空串长度为0 //注意:判断数组长度是length属性,判断字符串长度是length()方法 system.out.println("".isempty());//true //public string replace(char oldchar,char newchar) //返回一个将原字符串中所有的oldchar替换为newchar的新字符串,不改变原字符串 string s3 = "aaatttooo"; system.out.println( s3.replace('t','q'));//aaaqqqooo //public string replace(charsequence target,charsequence replacement) //charsequence可以看出string //将原字符串中的 target 全部换成 replacement string s4 = "abcsgdjsssjabcjdjjdjabc"; system.out.println(s4.replace("abc","www"));//wwwsgdjsssjwwwjdjjdjwww //public string[] split(string regex) //以regex为分界线,将字符串分割保存在一个字符串数组当中,并返回 string s5 = "2022-3-19"; string [] str = s5.split("-"); system.out.println(str[0] + str[1] + str[2]);//2022319 //public string substring(int beginindex) //返回一个以索引beginindex开始直至结尾的字符串 system.out.println("abcdefgh".substring(4));//efgh //public string substring(int beginindex,int endindex) //返回一个以索引值beginindex开始,以索引值endindex结束(不包含该索引值处的字符)的子字符串 system.out.println("abcdefgh".substring(2,5));//cde //public char[] tochararray() //将一个字符串以字符数组的形式返回 char[] str2 = "abcdefg".tochararray(); for(int i = 0 ; i < str2.length ; i++){ system.out.println(str2[i]); } //public string tolowercase() //返回一个将原字符串中所有字符变成小写的新字符串 system.out.println("abcdefg".tolowercase());//abcdefg //public string touppercase() //返回一个将原字符串中所有字符变成大写的新字符串 system.out.println("acbcdefg".touppercase());//abcdefg //public string trim() // 返回一个去除字符串的前后空白(空格)的新字符串 system.out.println(" abcdefg ".trim());//abcdefg //public static string valueof(参数列表) //参数列表可以是int型,char型,int数组,对象 等等....... //string类中唯一一个静态方法,可以直接调用 //将非字符串转换为字符串 //println()底层调用的就是valueof()方法,只要是打印在控制台上的都是字符串 system.out.println(string.valueof(true)); }}
stringbuffer类思考:
频繁使用字符串拼接会有什么影响?
java中字符串是不可变的,每拼接一次都会产生一个新的字符串
字符串是存在字符串常量池中的,频繁使用字符串拼接会占用大量的方法区空间
为了避免以上问题我们就可以使用到stringbuffer类
//java.lang.stringbufferpublic class stringbuffertest { public static void main(string[] args) { //创建一个初始化容量为16个 byte[] 数组(字符串缓冲区对象) stringbuffer strbuffer = new stringbuffer(); //拼接字符串调用 append()方法 //append()方法底层会调用 system.arraycopy()方法,效率较低 //append()再追加时,如果byte[]满了之后会自动扩容 strbuffer.append(1); strbuffer.append('q'); strbuffer.append(3.14); strbuffer.append("abc"); system.out.println(strbuffer);//1q3.14abc //stringbuffer可以进行一定的优化 //在创建stringbuffer时尽可能可能给定一个合适的初始化容量 //从而减少底层数组的扩容次数 //指定初始化容量的字符串缓冲区 stringbuffer newstrbuffer = new stringbuffer(100); }}
stringbuilder类它的用法与stringbuffer十分相似,但是也有很大的区别:
stringbuffer中的方法都有synchronized关键字修饰,表示stringbuffer在多线程编译环境下是安全的
stringbuilder中方法没有synchronized关键字修饰,表示stringbuilder在多线程编译环境下是不安全的
以上就是如何在java中使用string类、stringbuffer和stringbuilder?的详细内容。