【Java】java.lang.String类的使用

1.String类概述

image

  1. 该类声明为final,不可被继承。
  2. 实现了Serializable接口,表示字符串是支持序列化的。
  3. 实现了Comparable接口,表示String可以比较大小。
  4. 内部定义了final char[] value;数组用于存储字符串的数据。
  5. 通过字面量的方式创建实例(String str = "abc"),此时的字符串值声明在字符串常量池中。
  6. 字符串常量池中是不会存储相同内容的字符串的。可以使用String类的equals()比较。

2.String类的不可变性

以下几种情况需要重新指定内存区域赋值,不能使用原有的value进行赋值

  1. 当对字符串重新赋值时。
  2. 当对现有的字符串进行连接操作时。
  3. 当调用String的replace()方法修改指定字符或字符串时。
String s1 = "abc";
String s2 = "abc";
s1 = "hello";

image

  1. 比较地址值,重新赋值后不相等
        String s1 = "abc";
        String s2 = "abc";
        System.out.println(s1 == s2); //true

        s1 = "hello";
        System.out.println(s1 == s2);  //false
  1. 字符串连接后地址值不相等
        String s3 = "abc";
        s3+="def";
        System.out.println(s2==s3);  //false
  1. 使用replace方法后地址值不相等
        String s4 = "abc";
        String s5 = s4.replace('a','m');
        System.out.println(s4==s5);  //false

3.String实例化的不同方式

这两种方式的区别,字符串常量存储在字符串常量池,字符串对象存储在堆中。

String str1 = "abc";
String str2 = new String("abc");

image

s1和s2的数据"javaEE"声明在方法区中的字符串常量池中,s3和s4保存的地址值,是数据在堆空间中开辟空间以后对应的地址值。

        String s1 = "javaEE";
        String s2 = "javaEE";

        String s3 = new String("javaEE");
        String s4 = new String("javaEE");

        System.out.println(s1==s2); //true
        System.out.println(s1==s3); //false
        System.out.println(s3==s4); //false

4.字符串拼接和赋值对比

总结

  1. 常量与常量的拼接结果在常量池,且常量池中不会存在相同内容的常量。
  2. 只要其中一个是变量,结果就在堆中。
  3. 如果拼接的结果调用intern()方法,返回值就在常量池中。

常量与常量拼接

        String s3 = "javaEEhadoop";
        String s4 = "javaEE"+"hadoop";
        System.out.println(s3==s4); //true
		
        final String f4 = "javaEE";//s4:常量
        String f5 = s4 + "hadoop";
        System.out.println(f4 == f5);//true

存在变量

        String a = "javaEEE";
        String b = "hadoop";
        String s5 = a+"hadoop";
        String s6 = "javaEE"+b;
        String s7 = a+b;
		
        System.out.println(s3==s5);   //false
        System.out.println(s6==s7);   //false

调用了intern()

        String s8 = s6.intern();
        System.out.println(s3==s8);    //true

String类中的intern()方法:调用这个方法之后把字符串对象加入常量池中

5.String类常用方法

(1)第一波

方法 描述
int length() 返回字符串的长度 return value.length
char charAt(int index) 返回某索引处的字符 return value[index]
boolean isEmpty() 判断是否是空字符串 return value.length==0
String toLowerCase() 将所有字符转为小写
String toUpperCase() 将所有字符转为大写
String trim() 返回去除前后空格(空白)的字符串
boolean equals(Object obj) 比较字符串的内容是否相同
String concat(String str) 将指定字符串连接到此字符串的结尾,等价于用“+”
int compareTo(String anotherString) 比较两个字符串的大小

(2)第二波

方法 描述
String substring(int beginIndex) 返回从beginIndex开始截取到最后的字符串
String substring(int beginIndex,int endIndex) 返回从beginIndex开始截取到endIndex(不包含)的字符串,[beginIndex,endIndex)
boolean endsWith(String suffix) 字符串是否以指定的后缀结束
boolean startsWith(String prefix,int toffset) 字符串从指定索引开始的子字符串是否以指定前缀开始
boolean contains(CharSequence s) 当且仅当此字符串包含指定的char值序列时,返回true
int indexOf(String str) 返回指定子字符串在此字符串中第一次出现处的索引
int indexOf(String str,int fromIndex) 返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始
int lastIndexOf(String str) 返回指定子字符串在此字符串中最右边出现处的索引
int lastIndexOf(String str,int fromIndex) 返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索

注:indexOf和lastIndexOf方法如果未找到都是返回-1

(3)第三波

方法 描述
String replace(char oldChar,char newChar) 使用newChar替换字符串中出现的所有oldChar并返回
String replace(CharSequence target,CharSequence replacement) 使用replacement替换所有target,从左到右
String replaceAll(String regex,String replacement) 使用给定的replacement替换此字符串满足正则表达式的子字符串
String replaceFirst(String regex,String replacement) 使用给定的replacement替换满足正则表达式的第一个子字符串
boolean matches(String regex) 告知此字符串是否匹配给定的正则表达式
String [] split(String regex) 根据给定正则表达式的匹配拆分此字符串
String[] split(String regex,int limit) 根据匹配给定的正则表达式来拆分此字符串,最多不超过limit个,如果超过了,剩下的全部都放到最后一个元素中

6.String类与其他数据类型、结构的装换

(1)与基本数据类型、包装类之间的转换

  • String --> 基本数据类型、包装类:调用包装类的静态方法 parseXX(str)
  • 基本数据类型、包装类 --> String:调用String重载的valueOf(num) 或使用连接符
int num = Integer.parseInt(str1);

String str2 = String.valueOf(num);
String str3 = num + "";

(2)与字符数组之间的转换

  • String --> char[]:调用String类的toCharArray()方法
  • char[] --> String:调用String类的构造器
String str1 = "abc123";
char[] charArr = str1.toCharArray();

char[] arr = new char[]{'h','e','l','l','o'};
String str2 = new String(arr);

(3)与字节数组之间的转换

  • 编码:字符串 --> 字节(看得懂 --> 看不懂的二进制数据)

    • String --> byte[]:调用String的getBytes()方法
  • 解码:字节 --> 字符串(看不懂的二进制数据 -->看得懂)

    • byte[] --> String:调用String的构造器

说明:解码时,要求解码使用的字符集必须与编码时使用的字符集一致,否则会出现乱码。

String str1 = "abc123张三";
byte[] bytes = str1.getBytes();	//使用默认字符集进行编码
byte[] bytes2 = str1.getBytes("gbk");	//使用gbk字符集进行编码

String str2 = new String(bytes);	//使用默认字符集进行解码
String str3 = new String(bytes2,"gbk");

String str4 = new String(bytes2); //出现乱码,编码集和解码集不一致

(4)与StringBuffer、StringBuilder之间的转换

  • String --> StringBuffer、StringBuilder:调用StringBuffer、StringBuilder构造器
  • StringBuffer、StringBuilder --> String:调用String构造器或StringBuffer、StringBuilder的toString()

7.JVM中字符串常量池存放位置

  • jdk 1.6:字符串常量池存储在方法区(永久区)
  • jdk 1.7:字符串常量池存储在堆空间
  • jdk 1.8:字符串常量池存储在方法区(元空间)

8.String类常见题目

  1. String str1 = new String("abc");在内存中创建了几个对象?
    两个:一个是堆空间中new结构,另一个是char[]对应的常量池中的数据"abc"。

  2. 模拟一个trim方法,去除字符串两端的空格。

  3. 将一个字符串进行反转;将字符串中指定部分进行反转(如:"abcdefg"反转为"abfedcg")

  4. 获取两个字符串中最大相同子串,如:str1 = "abcwerthelloyuiodef"; str2 = "cvhellobnm";

提示:将短的那个串进行长度依次递减的子串与较长的串比较。

  1. 对字符串进行自然顺序排序。

提示:①字符串变成字符数组。②对数组进行排序(冒泡,Arrays.sort())。③将排序后的数组变成字符串。

参考链接
1.Java String类中的intern()方法
2.String replace(CharSequence target, CharSequence replacement)
3.初探JDK源码之默认字符集

posted @ 2022-11-22 14:35  植树chen  阅读(117)  评论(0编辑  收藏  举报