欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Java核心技术系列之华东师范大学Java核心技术第六章不可变对象和字符串

程序员文章站 2022-03-05 15:01:06
Java核心技术系列之华东师范大学Java核心技术第六章不可变对象和字符串可变对象与不可变对象定义如何创建不可变对象不可变对象优缺点字符串字符串拼接的效率区别传参的区别总结可变对象与不可变对象定义不可变对象的更改实际上是重新开辟新的数值空间,然后将指针指向新开辟的数值空间。举个例子,如何创建不可变对象不可变对象优缺点优点缺点只读,线程安全制造垃圾,浪费空间(对不可变对象进行修改时,会新开辟空间,旧对象则被搁置,直到垃圾回收)并发读,提高性能可以重复使用...

Java核心技术系列之华东师范大学Java核心技术第六章不可变对象和字符串

可变对象与不可变对象

定义

Java核心技术系列之华东师范大学Java核心技术第六章不可变对象和字符串
不可变对象的更改实际上是重新开辟新的数值空间,然后将指针指向新开辟的数值空间。举个例子,
Java核心技术系列之华东师范大学Java核心技术第六章不可变对象和字符串

如何创建不可变对象

Java核心技术系列之华东师范大学Java核心技术第六章不可变对象和字符串

不可变对象优缺点

优点 缺点
只读,线程安全 制造垃圾,浪费空间(对不可变对象进行修改时,会新开辟空间,旧对象则被搁置,直到垃圾回收)
并发读,提高性能
可以重复使用

字符串

Java核心技术系列之华东师范大学Java核心技术第六章不可变对象和字符串

Java常量池
保存在编译期间就已经确定的数据
是一块特殊的内存
相同的**常量字符串(new出来的不算)**只存储一份,节省内存,共享访问
package chapter6.String;

public class StringPassingTest {
    public static void main(String[] args) {
        String a = "abc";
        changeValue(a);
        System.out.println(a); // "abc"

        a = "abc";
        String b = a;
        a = "def";
        System.out.println(b); // "abc", 这是因为a会被常量化,b是新建的对象指向a,a重新赋值指针由原来指向 "abc" 变成指向 "def",但是字符串b不会改变。
    }

    private static void changeValue(String b) {
        b = "def";
    }
}

Java核心技术系列之华东师范大学Java核心技术第六章不可变对象和字符串

字符串拼接的效率区别

比较Java字符串中的+、StringBuilder(线程不安全)、StringBuffer(线程安全)三者之间的效率问题,代码StringAppendTest.java如下:

package chapter6.String;

import java.util.Calendar;

public class StringAppendTest {
    public static void main(String[] args) {
        int n = 50000;
        Calendar t1 = Calendar.getInstance();
        String a = new String();
        for (int i=0; i<n; i++) {
            a = a + i + ",";
        }
        System.out.println(Calendar.getInstance().getTimeInMillis() - t1.getTimeInMillis()); //3648

        // 线程安全
        Calendar t2 = Calendar.getInstance();
        StringBuffer b = new StringBuffer("");
        for (int i=0;i<n;i++) {
            b.append(i);
            b.append(",");
        }
        System.out.println(Calendar.getInstance().getTimeInMillis() - t2.getTimeInMillis()); // 5

        // 线程不安全
        Calendar t3 = Calendar.getInstance();
        StringBuilder c = new StringBuilder("");
        for (int i=0;i<n;i++) {
            c.append(i);
            c.append(",");
        }
        System.out.println(Calendar.getInstance().getTimeInMillis() - t3.getTimeInMillis()); // 2
    }
}

因此,如果涉及到大量字符串拼接操作,建议使用 StringBuffer 或者 StringBuilder。

传参的区别

  • 当函数参数是基本类别变量时,是传值的。拷贝value给到形参,外围的参数不变。
  • 当函数参数是对象时,传入的是指针。
package chapter6.String;

public class ArgumentPassing {
    public static void main(String[] args) {
        int a = 5;
        String b = "abc";
        StringBuffer c = new StringBuffer("abc");
        changeValue(a);  // 实参=5,形参=5
        changeValue(b);
        changeValue(c);
        System.out.println(a); // 5
        System.out.println(b); // "def"
        System.out.println(c); // "abcdef"
    }

    private static void changeValue(StringBuffer s1) {
        s1.append("def");
    }

    private static void changeValue(String s1) {
        s1 = "def";
    }

    private static void changeValue(int a) {
        a = 10; // 实参=5,形参=10
    }
}

总结

Java核心技术系列之华东师范大学Java核心技术第六章不可变对象和字符串
但是StringBuffer线程安全。

本文地址:https://blog.csdn.net/woai8339/article/details/109911188