String类
字符串时常量,创建后面不可改变 String的内部数据是一个char数组,是对字符串数组的封装,并且是被final修饰的,创建后不可改变
字符串字面值存储在字符串池中,可以共享,在方法区里 (内存有堆,栈,方法区)JDK8以后方法区移入堆中
如果可变 会大量的使用String常量,如果每一次声明一个String都创建一个String对象,那将会造成极大的空间资源的浪费
package studyObject.packet; public class Demo03 { public static void main(String[] args) { String name = "hello";//hello常量存储在方法区的字符串池中,只产生一个对象,字符串池中存储 /* 这里对name重新赋值,并没有把hello覆盖掉, 是重新在字符串池中开辟一块空间存储zhang 然后name重新指向zhang */ name = "zhang"; /* 这里会先去字符串池找到zhang 然后name2指向zhang name和name2指向同一个对象 */ String name2 = "zhang"; /* 产生两个对象,堆,池各存储一个, 堆是new 池是hello2这个常量 如果池中已经有hello2 就不会开辟新对象 指向 : s----》堆的地址 -----》字符串池的地址 */ String s = new String("hello2"); String s2 = new String("hello2"); System.out.println(s==s2);//结果false 因为s----》堆的地址 -----》字符串池的地址,两个堆的地址不一样 System.out.println(s.equals(s2));//true 因为Sting类中的equals方法重写了是比较内容,而不是原先的比较方法 } }
面试题地址:
String对象数目(难度:★★★ 频率:★)
如何修改String对象的数据?(难度:★★★ 频率:★★)
Java-String不可变的含义、原因、好处 – 自学精灵
常用方法
length 返回字符串长度
charAt(int index) 根据下标获取字符
contains(String str) 判断当前字符串中是否含有str
String content = "java是世界第一"; System.out.println(content.length()); System.out.println(content.charAt(6)); System.out.println(content.contains("java")); ========================结果: 9 界 true
toCharArray 将字符串转换成数组
indexOf(String str) 查找str在字符串中第一次出现的下标,存在返回下标,不存在返回-1
lastIndexOf(String str)查找str在字符串中最后一次出现的下标
String content2 = "java是世界第一,java,jajjjj"; System.out.println(Arrays.toString(content2.toCharArray())); System.out.println(content2.indexOf("java")); System.out.println(content2.indexOf("java",4));//从下标4后面开始找 System.out.println(content2.lastIndexOf("java")); ========================2 [j, a, v, a, 是, 世, 界, 第, 一, ,, j, a, v, a, ,, j, a, j, j, j, j] 0 10 10
trim 去除字符串前后空格。
toUpperCase 小写转换车大写
toLowerCase 大写变小写
endsWith(String str) 判断字符串是否以str结尾
startsWith(String str) 判断字符串是否以str开头
String content3 = " java是世界第一,java,jajj jj "; System.out.println(content3.trim()); System.out.println(content3.toUpperCase()); System.out.println(content3.toLowerCase()); System.out.println(content3.endsWith("jj")); System.out.println(content3.endsWith(" ")); System.out.println(content3.startsWith("java")); ========================3 java是世界第一,java,jajj jj JAVA是世界第一,JAVA,JAJJ JJ java是世界第一,java,jajj jj false true false
replace(char oldChar,char newChar) 将旧字符串替换为新字符串
split(String str) 根据str 做拆分
String content4 = "java世界第一,java最好"; System.out.println(content4.replace("java","c++")); String content5 = "java id the best programing language,java hh"; //[]里面的表示选择可以用哪些拆分,这里是空格和逗号 + 表示前面的空格和逗号可以连续出现多个 String[] arr = content5.split("[ ,]+"); for (String s1 : arr) { System.out.println(s1); } ========================4 c++世界第一,c++最好 java id the best programing language java hh
补充方法:
//补充 String ss1 = "hello"; String ss2 = "Hello"; System.out.println(ss1.equalsIgnoreCase(ss2));//比较字符串 不区分大小写 String ss3 = "abc";//a:97 String ss4 = "xyz";//x:120 System.out.println(ss3.compareTo(ss4));//比较大小 结果97-120 只比较第一个 String ss5 = "abc";//a:97 String ss6 = "a";//a:97 System.out.println(ss5.compareTo(ss6));//比较大小 结果3-1 第一个一样 就比较长度
案例:
package studyObject.packet; public class Demo04 { public static void main(String[] args) { String str = "this is a text"; //将单词提取出来 String[] str1 = str.split(" "); for (String s : str1) { System.out.println(s); } System.out.println("=============="); //将text替换为practice String str2 = str.replace("text","practice"); System.out.println(str2); System.out.println("=============="); //在text前面添加easy String str3 = str.replace("text","easy text"); System.out.println(str3); System.out.println("=============="); //将单词首字母大写 String[] str4 = str.split(" "); for ( int i=0;i< str1.length;i++) { char first = str4[i].charAt(0);//获得第一个字符 char upperFirst = Character.toUpperCase(first);//把第一个字符转大写 String news = upperFirst+str1[i].substring(1);//把大写和后面的拼接起来 System.out.println(news); } } } /* this is a text ============== this is a practice ============== this is a easy text ============== This Is A Text */
StringBuffer:可变长字符串 JDK1.0提供 运行效率慢 线程安全
StringBuilder:可变长字符串 JDK5.0提供 运行效率快 线程不安全
两种的使用方法
package studyObject.packet; /* StringBuffer 和 StringBuilder 的使用 比String效率高,节省内存 */ public class Demo05 { public static void main(String[] args) { // StringBuffer sb = new StringBuffer(); StringBuilder sb = new StringBuilder(); //两个使用方法一样, 推荐单线程使用StringBuilder 速度快 //多线程使用StringBuffer 线程安全 他的方法都添加了锁synchronized //1 append() 追加 sb.append("java世界第一"); System.out.println(sb); sb.append(",java最好"); System.out.println(sb); //2 insert() 插入 sb.insert(0,"我在最前面");//从sb下标为0的位置开始插入 System.out.println(sb); //3 replace 替换 sb.replace(0,5,"hello");//替换下标0--4的,含头不含尾 System.out.println(sb); //4 delete() 删除 sb.delete(0,5);//删除下标0---5,含头不含尾 sb.reverse();//反转 System.out.println(sb); } /* 结果: java世界第一 java世界第一,java最好 我在最前面java世界第一,java最好 hellojava世界第一,java最好 好最avaj,一第界世avaj */ }
测试运行效率:
package studyObject.packet; /* 验证StringBuffer 和 StringBuilder 的效率高于String StringBuilder 效率高于 StringBuffer 因为StringBuffer 的方法都添加了锁synchronized */ public class Demo06 { public static void main(String[] args) { long start = System.currentTimeMillis(); String string = "";//用时:16245 // StringBuilder string = new StringBuilder();//用时:23 // StringBuffer string = new StringBuffer();//用时:27 for (int i = 0; i < 99999; i++) { string+=i; // string.append(i); } System.out.println(string); long end = System.currentTimeMillis(); System.out.println("用时:"+(end-start)); } }
String, StringBuffer, StringBuilder区别(难度:★ 频率:★★★)
Java-String, StringBuffer, StringBuilder的区别 – 自学精灵
intern方法
-
说明:
-
从字符串常量池中查询当前字符串是否存在(通过equals判断)。
-
如果存在,返回常量池中的字符串引用。
-
如果不存在,把这个String对象引用存到常量池,然后返回这个String对象的引用。
-
返回值:都是返回String变量对应的常量池中字符串的引用。
-
-
JDK6及以前调用String.intern()
-
若常量池中有,则返回常量池中这个字符串的引用
-
若常量池中没有,则拷贝一份对象,放到常量池(永久代)中;返回值是常量池(永久代)中对应字符串实例的引用。
-
-
JDK7及以后调用String.intern()
-
若常量池中有,则返回常量池中这个字符串的引用
-
若常量池中没有,则拷贝一份引用,放到常量池(堆)中;(JDK1.7将String常量池从Perm区移动到了Java Heap区)
-
intern方法的作用(难度:★★★ 频率:★)