不可变对象
- 一旦创建,这个对象(状态/值)不能被更改
- 其内在成员变量的值就不能修改
- 八个基本类型的包装类对象
- String,BigInteger和BigDecimal等
注:不可变对象是指值对象不再修改,而指针的指向可以修改
可变对象
- 普通对象
如何创建不可变对象
- 所有属性都是final和private的
- 不提供set方法
- 类是final的,或者所有方法都是final的
不可变对象优点
- 只读,线程安全
- 并发读,提高性能
- 可以重复使用
不可变对象缺点
- 对不可变对象进行修改时会开辟新空间,旧对象则被搁置,直到垃圾回收
- 制造垃圾,浪费空间
例子:
public class ArgumentPassing {
public static void changeValue(int a)
{
a = 10;
}
public static void changeValue(String s1)
{
s1 = "def";
}
public static void changeValue(StringBuffer s1)
{
s1.append("def");
}
public static void main(String[] args) {
int a = 5; //基本类型
String b = "abc"; //不可变对象
StringBuffer c = new StringBuffer("abc"); //可变对象
changeValue(a);
changeValue(b);
changeValue(c);
System.out.println(a);
System.out.println(b);
System.out.println(c);
}
```
运行结果:
5
abc
abcdef
在函数传递上:
- 不可变对象,是传递指针,故形参s1拿到了a的指针,指向"abc", 由于不可变,临时变量指向新内存,外部实参的指针不改动,s1指向"def",而外部的a仍旧指向"abc","def"是重新申请的内存
- 基本类型是值传递
- 可变对象,形参也是拿到实参的指针,跟实参指向同一片内存,但此时对该对象做修改时不会另外申请空间,而是原地扩张
附:
String类
- 字符串是Java使用最多的类,是一种典型的不可变对象
- String定义有两种
- String a=“abc”;//常量赋值,栈分配内存
- String b =new String(“abc”);//new对象,对分配内存(不会被常量化)
- 字符串内容比较:equals方法
- 是否指向同一个对象:指针比较==
字符串加法
- String a = “abc”;a=a+“def”;由于String不可修改,所以a指向的"abcdef"是重新申请的空间,原来的"abc"搁置
- 使用StringBuffer/StringBuilder类的Append方法,二者的对象都是可变对象
- StringBuffer(同步,线程安全,修改快速)
- StringBuilder(不同步,线程不安全,修改更快)
三者时间比较
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());
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());
Calendar t3 = Calendar.getInstance();
StringBuilder c = new StringBuilder("");
for(int i=0;i<n;i++)
{
b.append(i);
b.append(",");
}
System.out.println(Calendar.getInstance().getTimeInMillis() - t3.getTimeInMillis());
}
}
运行结果:
5837
9
3
注:+50000次,速度的提高是惊人的,适合大量字符串的加法操作