不可变对象
  • 一旦创建,这个对象(状态/值)不能被更改
  • 其内在成员变量的值就不能修改
  • 八个基本类型的包装类对象
  • 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定义有两种
  1. String a=“abc”;//常量赋值,栈分配内存
  2. 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次,速度的提高是惊人的,适合大量字符串的加法操作