《java基础》——String,StringBuffer和StringBuilder

1.String

String是一个用final修饰的类,该类中存在一个final修饰的 ‘char[]’ 数组用于保存字符串,String的部分源码如下:

在这里插入图片描述
所以String类第一次赋值后的不可再改变,如需要修改会重新创建一个新的Sting对象进行赋值,因此在每次对 String 类型进行改变的时候其实都等同于生成了一个新的 String 对象,然后将指针指向新的 String 对象,所以经常改变内容的字符串最好不要用 String(建议使用StringBuilder),因为每次生成对象都会对系统性能产生影响,特别当内存中无引用对象多了以后, JVM 的 GC 就会开始工作,那速度是一定会相当慢的。

String 常用方法:
		String s1 = "";
        // 执行完for循环后相当于创建了20个对象(10个s1和i)会导致jvm的垃圾回收器频繁工作从而降低系统的性能
        for (int i = 0; i < 10; i++) {
            s1 = s1 + i; 
        }
        System.out.println(s1);
        // 如果字符串以prefix开始,则返回true
        System.out.println(s1.startsWith("prefix")); // false
        // 如果字符串以suffix结尾,则返回true
        System.out.println(s1.endsWith("suffix")); // false
        
        // 返回一个新的字符串,即创建新的String对象
        String s2 = s1.substring(2); // 从索引为2起一直等到结尾
        String s3 = s1.substring(2, 5);// 从索引为2起一直到索引5(不包括索引为5的字符)
        System.out.println(s2);  
        System.out.println(s3);
        
        String s4 = "abcDEF";
        System.out.println(s4.toLowerCase()); // 大写改小写
        System.out.println(s4.toUpperCase()); // 小写改大写

执行结果:
在这里插入图片描述

String的注意点:
public class TestStringAndStringBuilderAndStringBuffer {

    public static void main(String[] args) {

        String s5 = "a" + "b"; // 编译器做了优化,直接在编译的时候进行字符串的拼接,相当于s5 = "ab";
        String s6 = "ab";
        System.out.println(s5 == s6); // true
        String s7 = "a";
        
        /*
         * 编译的时候不知道变量中存储的是什么,所以没办法在编译的时候进行优化拼接,
         *          只有在程序运行后才确定s8的内容,所以程序会创建一个新的对象
         */
        String s8 = s7 + "b"; 
        System.out.println(s6 == s8); // false
        
        /*
         * 当final变量是基本数据类型以及String类型时,如果在编译期间能知道它的确切值,
         * 则编译器会把它当做编译期常量使用。也就是说在用到该final变量的地方,
         * 相当于直接访问的这个常量,不需要在运行时确定。
         * 因此在下面的一段代码中,由于变量 s9 被final修饰,因此会被当做编译器常量,
         * 所以在使用 s9 的地方会直接将变量 s9 替换为它的值。
         * 不过要注意,只有在编译期间能确切知道final变量值的情况下,编译器才会进行这样的优化
         */
        final String s9 = "a";
        String s10 = s9 + 'b';  // 因为变量 s9 用了final修饰且s9的值在编译时以确定所以等同于 s10 = "a" + "b"
        System.out.println(s6 == s10); // true
        
        /*
         * 注意:虽然s11也是被final修饰,但在编译时期s11的值是不确定的,这里的getA()只有在运行时才确定值
         */
        final String s11 = getA();
        String s12 = s11 +"b";
        System.out.println(s6 == s12); // false
    }
    
    public static String getA() {
        return "a";
    }

}

执行结果:
在这里插入图片描述

StringBuffer和StringBuilder

区别

1、StringBuffer 与 StringBuilder 中的方法和功能完全是等价的,
2、只是StringBuffer 中的方法大都采用了 synchronized 关键字进行修饰,因此是线程安全的,而 StringBuilder 没有这个修饰,可以被认为是线程不安全但是效率会更高(常用)。
3、在单线程程序下,StringBuilder效率更快,因为它不需要加锁,不具备多线程安全而StringBuffer则每次都需要判断锁,效率相对更低

StringBuffer和StringBuilder都是继承了AbstractStringBuilder抽象类,其中AbstractStringBuilder抽象类部分源码如下:

在这里插入图片描述

因为没有final修饰所以StringBuffer和StringBuilder对象里的内容是可变的,每次进行字符串的修改时不会产生新的对象,在内存使用上要优于String类。所以在实际使用时,如果经常需要对一个字符串进行修改,例如插入,删除等操作,使用StringBuilder要更加适合一些。代码示例如下
		// StringBuilder线程不安全,效率高(一般使用它),StringBuffer线程安全,线程安全
        StringBuilder sb1 = new StringBuilder("abc");
        System.out.println(Integer.toHexString(sb1.hashCode()));
        System.out.println(sb1);
        sb1.setCharAt(0, 'A');
        System.out.println(Integer.toHexString(sb1.hashCode()));
        System.out.println(sb1);
执行结果

在这里插入图片描述

StringBuilder与String

直接上代码
/*使用String进行字符串拼接*/
        String s = "";
        // 本质上使用String进行拼接,但是每次循环都会生成一个String对象
        long memory1 = Runtime.getRuntime().freeMemory(); // 获取系统剩余内存空间
        long time1 = System.currentTimeMillis(); // 获取系统当前时间
        for (int i = 0; i < 1000; i++) {
            s = s + i; // 相当于产生了2000 个对象
        }
        long memory2 = Runtime.getRuntime().freeMemory(); // 获取系统剩余内存空间
        long time2 = System.currentTimeMillis(); // 获取系统当前时间
        System.out.println("String 占用内存: " + (memory1 - memory2));
        System.out.println("String 占用时间: " + (time2 - time1));
        
        /*使用StringBilder进行字符串拼接*/
        StringBuilder sb = new StringBuilder("");
        // 本质上使用String进行拼接,但是每次循环都会生成一个String对象
        long memory3 = Runtime.getRuntime().freeMemory(); // 获取系统剩余内存空间
        long time3 = System.currentTimeMillis(); // 获取系统当前时间
        for (int i = 0; i < 1000; i++) {
            sb.append(i);
        }
        long memory4 = Runtime.getRuntime().freeMemory(); // 获取系统剩余内存空间
        long time4 = System.currentTimeMillis(); // 获取系统当前时间
        System.out.println("StringBuilder 占用内存: " + (memory3 - memory4));
        System.out.println("StringBuilder 占用时间: " + (time4 - time3));
        
执行结果

在这里插入图片描述

总结:
对于经常需要对一个字符串进行修改,例如插入,删除等操作,使用StringBuilder要会比用String效率更高;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值