这几天有在读一些关于并发的书,然后在一本书上看到了这么一个描述:在Java中,Integer属于不变对象,也就是对象一旦被创建,就不可能被修改。这段描述是讲Integer的对象,当初始化之后这个对象的内容就不能够改变了,对Integer的操作,都会新建一个对象。
换句话讲,Integer对象与Streing表现出来的性质是一样的。然后了解了一下,发现在Java中,不仅仅是Integer类,Double、Float等类都是不可变的。然后我测试了一下基本类型的不变性。
自动包装
Java中存在着这么一个机制:int、double、float等都是一些声明变量的关键字,通过这些关键字进行声明的变量,会在实际处理的时候自动封装成为包装器类型。也就是说,int变量会被包装Integer,同理double和float等也会进行相应处理。
不变性的测试
在包装器类型中,声明的对象是不可变类型,那么声明的基本数据类型是不是也是不可变的,我测试了一下。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
| public class AutoPackageTest {
public static void main(String[] args) { integerTest(); longTest(); doubleTest(); floatTest(); }
public static void integerTest(){
System.out.print("This is IntegerTest:");
Integer integer = 1; Integer integerU = integer;
int a = 1; int b = a;
a++;integer++;
System.out.print(integer + " "); System.out.print(integerU + " "); System.out.print(a+ " "); System.out.println(b); }
public static void longTest(){
System.out.print("This is LongTest:");
Long aLong = 1L; Long aLongU = aLong;
long a = 1L; long b = a;
aLong++;a++;
System.out.print(aLong + " "); System.out.print(aLongU + " "); System.out.print(a+ " "); System.out.println(b); }
public static void doubleTest(){
System.out.print("This is DoubleTest:");
Double c = 1D; Double d = c;
double a = 1D; double b = a;
c++;a++;
System.out.print(c + " "); System.out.print(d + " "); System.out.print(a+ " "); System.out.println(b); }
public static void floatTest(){
System.out.print("This is FloatTest:");
Float c = 1F; Float d = c;
float a = 1; float b = a;
c++;a++;
System.out.print(c + " "); System.out.print(d + " "); System.out.print(a+ " "); System.out.println(b); } }
|
运行上述程序,产生的结果是这样的:

也就是说,通过基本数据类型定义的变量,实际上也会产生一个不可变对象,在经过操作之后,也是通过新建一个新的对象来实现的。
所以在实际应用过程中,对基本类型或者自动包装类型加锁的时候,要注意加锁的对象,是不是当前的实例,新建对象的创建可能会造成加锁对象的改变。