总结Java中的String类。



文章目录

  • String类
  • 1.类中常用方法
  • 2.String类的赋值和intern方法
  • 3.String类的不可变性
  • 4.StringBuilder类和StringBuffer类



String类

字符串内部是使用字符数组char[] value来存储内容的,字符串是一种线性表(线性表还包括数组、链表等)。


1.类中常用方法

返回类型

方法名称

作用

char

charAt(int)

得到指定下标位置对应的字符

int

indexOf(String)

得到指定内容第一次出现的下标

int

lastIndexOf(String)

得到指定内容最后一次出现的下标

int

length()

得到一个字符串的字符个数

char[]

toCharArray()

将一个字符串转换成字符数组

String[]

split(String)

将一个字符串按照指定内容劈开

byte[]

getBytes()

将一个字符串转换成字节数组

boolean

equals(String)

判断两个字符串的内容是否相同

boolean

equalsIgnoreCase(String)

忽略大小写比较两个字符串的内容是否相同

boolean

contains(String)

判断一个字符串里面是否包含指定的内容

boolean

startsWith(String)

判断一个字符串是否以指定的内容开头

boolean

endsWith(String)

判断一个字符串是否以指定的内容结尾

String

toUpperCase()

将一个字符串全部转换成大写

String

toLowerCase()

将一个字符串全部转换成小写

String

replace(String,String)

将某个内容全部替换成指定内容

String

repalceFirst(String,String)

将第一次出现的某个内容替换成指定的内容

String

substring(int)

从指定下标开始一直截取到字符串的最后

String

substring(int,int)

从下标x截取到下标y-1对应的元素

String

trim()

去除一个字符串的前后空格


2.String类的赋值和intern方法

public class test {
    public static void main(String[] args) {
        String str1 = "hello";
        String str2 = "hello";
        String str3 = new String("hello");
        String str4 = new String("hello");
        System.out.println(str1 == str2);
        System.out.println(str1 == str3);
        System.out.println(str3 == str4);
    }
}

输出:
true
false
false

解释:
采用直接赋值:String str = "字符串字面量"的方式创建字符串对象,会在堆区使用字符串的常量池,若该对象是第一次出现,就在堆中开辟新空间,产生新对象,产生之后将该对象置入字符串的常量池,当下次再次使用该对象时(还是采用直接赋值的方式),若常量池中已有该内容的字符串,直接引用常量池中的对象,将该字符串的地址赋值给str,不再创建字符串。
若使用String str = new String(“字符串字面量”)的方式创建字符串对象,则在堆区的常量池外开辟一块空间,空间里面储存该字符串,将该空间的地址赋值过去str。

字符串的intern方法:

作用:调用这个inern方法,会将产生的字符串对象置入常量池(若不存在则置入),若常量池中已存在该对象,则返回常量中的字符串对象引用(返回地址)。

示例1:字符串比较

public static void main(String[] args) {
        String str1 = "hello";
        String str2 = "hello";
        String str3 = new String("hello");
//        str3=str3.intern();
        System.out.println(str1 == str2);
        System.out.println(str1 == str3);
    }

输出:
true
false

示例2:在常量池中已有字符串情况下intern()方法使用

public static void main(String[] args) {
        String str1 = "hello";
        String str2 = "hello";
        String str3 = new String("hello");
        //此时常量池中已有"hello"对象,返回常量池中的hello对象的地址
        str3=str3.intern();
        System.out.println(str1 == str2);
        System.out.println(str1 == str3);
    }

输出:
true
true

示例3:在常量池中没有字符串情况下intern()方法使用

3.1:"abc"字符串第一次出现在intern()方法后面:

public static void main(String[] args) {
        char[] ch=new char[]{'a','b','c'};
        String s1=new String(ch);
        s1.intern();
        String s2="abc";
        System.out.println(s1 == s2);
    }

输出:
true

图解:

Android String boolen数组 string数组 java_字符串

解释:“abc"出现在intern()字符之后,则调用intern时,常量池中没有"abc”,所以intern()方法的作用是将常量池外面的"abc"移动到常量池内部,s1的地址值不改变,s2赋值时,常量池中已有该字符串,返回该字符串的地址,所以最后输出true。

3.2:"abc"字符串第一次出现在intern()方法前面:

public static void main(String[] args) {
        String s1=new String("abc");
        s1.intern();
        String s2="abc";
        System.out.println(s1 == s2);
    }

输出:
false

解释:“abc"出现在intern()字符之前,则调用intern时,常量池中已有"abc”,所以intern()方法的作用是返回的是常量池中"abc"的地址,但没有被接收,所以s1的地址值没有改变,返回false。


3.String类的不可变性

当一个字符串的对象产生之后,他的内容就无法修改,这称之为字符串对象的不可变性。

示例:

public static void main(String[] args) {
        String str = "hello";
        str += "world";
        str += "!!!";
    }

图示:

Android String boolen数组 string数组 java_bc_02

因为字符串的不可变性,在执行str += “world"时,会先在堆区的常量池中产生一个"world"对象,然后再产生一个"helloworld"对象,最后把str的引用改为指向"helloworld”,执行str += "!!!"时同理。正是由于字符串对象的不可变性,因此当直接使用字符串对象进行+=操作的时候会产生大量的临时对象,浪费内存!


面试问题:结合String的源码来分析一下为什么唯独字符串对象的内容无法修改?(你怎么理解字符串对象不可变,是如何做到内容无法修改的?)

源码:

Android String boolen数组 string数组 java_bc_03

解答:有很多错误的理解在于value数组被final修饰导致内容不能改,其实不是这样的!!!这里final修饰的是引用数据类型,不能修改的是该类型的地址值,而不是里面保存的具体内容。其本质在于在String类中,private关键字将value数组完全封装,且对外没有提供任何获取或者修改该value内容的方法,所以String类外部完全无法拿到这个value数组,因此字符串对象一旦产生,内容无法修改!!!


面试问题:string具有不可变性,Sting类内部有很多操作字符串的方法,如subString截取字符串,替换replace等等方法看起来这不都在修改字符串对象内容吗?

解答:String类的内部提供的所有涉及字符串修改的方法,都会产生新的字符串对象,并不会影响原字符串对象。


4.StringBuilder类和StringBuffer类

String、StringBuilder、StringBuffer区别:

String

StringBuffer

StringBuilder

执行速度


中等


线程安全

线程安全

线程安全

线程不安全

使用场景

少量字符串操作

多线程环境下的大量操作

单线程环境下的大量操作

PS:正常做题大部分情况下都使用StringBuilder。


面试问题:String.StringBuilder、StringBuffer的区别?

1.String的内容无法修改,StringBuffer、StringBuilder的对象内容可以修改,因此我们一般在字符串对象频繁修改的时候使用StringBuilder或StringBuffer类;
2.StringBuilder和StringBuffer的方法使用完全一致,StringBuffer采用同步处理,线程安全,效率较低;
3.StringBuilder采用异步处理,线程不安全,效率较高,开发中若不考虑线程安全问题,一般推荐使用StringBuilder类进行字符串内容的修改。