在Java中基础类型的包装类都是不可变的类,如Boolean、Byte、Character、Double、Float、Integer、Long、Short,另外还有String。
这些类创建的实例都是不可以变的实例。

//Integer类代码 JDK1.8
public final class Integer extends Number implements Comparable<Integer> {
	private final int value;
	public Integer(int value) {
		this.value = value;
	}
}

可以看到Integer类是final类型的不可被继承,其封装的int值是也是final的。这就导致了实例创建后我们没有其他办法去修改这个int值,所以说Integer对象是不可变对象。

那不可变对象又是如何提高性能的呢,这里看Integer的valueOf方法。

    public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

Integer在调用valueOf时是先从IntegerCache查找对象,如果没有才去创建一个新的对象,有的话就直接将引用指向这个对象。IntegerCache是个静态内部类,存储了-128到127的值的对象数组。
因为Integer对象是不可变的,这样这个缓存数组就可以在多个线程中进行共享,减少Integer对象的创建。
比如你通过一个ORM框架查询出1万条人员数据,人员数据使用Person类封装,Person类有一个字段Integer sex存储性别数据,1男2女。实例化这1万个Person类的时候就可以将这1万个Integer sex分别指向Integer(1)和Integer(2)的内存地址。如果张三的当前性别是男,你想改成女,那就把sex的引用指向缓存中Integer(2)的内存地址。这样的话在没有创建任何额外的Integer实例的情况下,达到了节省内存的目的。
反过来看,如果对象是可变的,就没法做缓存了。对象内部int值变化会导致所有对这个对象的引用不安全,就必须为每个Person创建一个Integer sex对象。

07-04 20:07