Java核心技术系列之华东师范大学Java核心技术第六章不可变对象和字符串
程序员文章站
2022-03-05 15:01:06
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字符串中的+、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
}
}
总结
但是StringBuffer线程安全。
本文地址:https://blog.csdn.net/woai8339/article/details/109911188