String类,String、StringBuffer、StringBuilder、StringTokenizer

发布时间 2023-05-21 22:05:27作者: 4加1等于9

String类

String

字符串:一串连续的字符,也是一串连续的char,Java中将char数组进行封装来表达字符串。

image-20230521211509068

String是不可变性,即对象本身的属性或对象本身的数据不变,重新赋值是变量(存放在堆中)指向堆中新创建的对象;可变的:可以修改对象的属性

image-20230521205828406

查看String源码可以观察到,final修饰的char数组且为私有成员变量(private);

final修饰表示其不能指向新的数组、表示其不能有子类不可被继承从而杜绝了子类覆盖父类行为的可能,不能代表数组本身的数据不会被改变;

String真正不可变的原因是其被final修饰的同时还被private修饰,且String没有暴露和提供任何修改数组的方法。

不可变的优点:

①不可变时字符串常量池(也存放在堆中)才能发挥作用。用自变量创建字符串时,字符串常量池会返回已有对象的引用;若字符串可变引用的值就能随时修改并随时影响其他对象的引用,从而使数据发生各种错误,不能进行常量池的复用。

②其哈希码也不会变,计算哈希码后可缓存不需要再计算,性能更高。

③不可变对象线程是安全的,不用担心当前线程使用的对象会被其他线程修改。

其他不可变对象:BigDecimal(java.math包中,用来对超过16位有效位的数进行精确的运算)。

StringBuffer

不可变弊端:频繁操作字符串时,会产生许多新对象,从而导致性能低下。——>引出StringBuffer

image-20230521213725401
abstract class AbstractStringBuilder{
char[] value;
}

查看StringBuffer源码,StringBuffer继承的AbstractStringBuilder没有final、private修饰,且StringBuffer有许多方法(例如append()在原字符后面添加字符)供我们修改字符串本身,以方便链式调用。

StringBuilder

StringBuffer可变所以其线程不安全,——>引出StringBuilder

StringBuilder也继承AbstractStringBuilder,每次操作字符串时都会加锁,导致性能低下。

总结

类型 特点 适用场景
String 不可变,线程安全 少量或不操作数据
StringBuffer 可变,线程不安全 大量操作数据且无需考虑线程安全性
StringBuilder 可变,线程安全性能较低 大量操作数据且需要考虑线程安全性

Test

class StringClass{
    public static void testString(){
        String s="hello";
        String s1="world";
        long start=System.currentTimeMillis();
        for(int i=0;i<10000;i++){
            s+=s1;
        }
        long end=System.currentTimeMillis();
        long runTime=(end-start);
        System.out.println("String加长所需时间为"+runTime);
    }
    public static void testStringBuffer(){
        StringBuffer s=new StringBuffer("Hello");
        String s1="world";
        long start=System.currentTimeMillis();
        for(int i=0;i<10000;i++){
            s.append(s1);
        }
        long end=System.currentTimeMillis();
        long runTime=(end-start);
        System.out.println("StringBuffer 加长所需时间为"+runTime);
    }
    public static void testStringBuilder(){
        StringBuilder s=new StringBuilder("hello");
        String s1="world";
        long start=System.currentTimeMillis();
        for(int i=0;i<10000;i++){
            s.append(s1);
        }
        long end=System.currentTimeMillis();
        long runTime=(end-start);
        System.out.println("StringBuilder加长所需时间为"+runTime);
    }
    public static void main(String[] args){
        testString();
        testStringBuffer();
        testStringBuilder();
    }
}
image-20230521215341970

StringTokenizer

StringTokenizer是用来分割字符串的工具

class StringClass{
    public static void main(String args[]){
        StringTokenizer st=new StringTokenizer("my name is lzm");
        while(st.hasMoreTokens()){
            System.out.println(st.nextToken());
        }
    }
}
image-20230521215715267