常量是不会被修改的,在内存空间中,只需要保留一份、只读。Java语言设计对只读的对象进行了设计,叫做不可变对象
不可变对象(1):(Immutable Object)
--一旦创建之后,这个对象的值或者对象的状态就不能被更改了
--其内在的成员变量的值就不能修改了
--八个基本型别的包装类属于不可变对象
--String、BigInteger和BigDecimal等属于不可变对象
可变对象(Mutable Object):与不可变对象相对应。
--普通对象(Man、Human都属于普通对象,可变对象)
不可变对象(2):
a是一个不可变对象,一开始a指向的是“abc”。后来a = “def”; 不可变对象是指值对象不再修改,即abc不会被修改,而指针(句柄/变量名) a的指向可以修改,所以a指向“def”;而b的指向不变啊,所有打印b还是“abc”。
其中a = "def"; 相当于先申请一个存储“def”的内存空间,再把这个内存空间的地址赋给对象a。
--不可变对象,也是传入指针(引用)。change(a); 使得首先b也指向“abc”,然后b = "def",String对象b是不可变对象,只能改变指针指向,于是开始指向“def”,但是a的指向不变。
--由于不可变,临时变量(b)指向新的内存,外部实参(a)的指针不改动。
不可变对象(3):
如何创建不可变对象:(除了上述几个不可改变的对象,能不能自己做出不可改变对象)
(1)immutable对象是不可改变的,有改变,请clone/new一个对象进行修改
(2)所有的属性都是final和private的
(3)不提供setter方法
(4)类是final,或者所有的方法都是final。(不可通过重写的方法来修改类的方法)
(5)类中包含mutable对象(可变对象),那么返回拷贝需要深度clone
不可变对象(4):
--不可变对象(Immutable Object)
优点:
只读的,线程安全
并发读,提高性能
可以重复使用
缺点:制造垃圾,浪费空间(由于变量繁多,会制造处很多变量的垃圾)
Java字符串(1):
--字符串是Java中使用最多的类,是一种典型的不可变对象
--String的定义有2种:
String a = " abc " ; //常量赋值, 栈分配内存
String b = new String (" abc ") ; // new对象,堆分配内存
--字符串内容比较: equals 方法
--是否指向同一个对象: 指针比较 == (比较两个变量是否指向同一个内存)
Java字符串(2):
Java常量池(Constant Pool)
--保存在编译期间就已经确定的数据
--是一块特殊的内存
--相同的 常量字符串 只存储一份,节省内存,共享访问
Java字符串(3):
--字符串的加法
--String a = " abc " ;
a = a + " def " ; // 由于String不可修改,效率差(申请一个新的空间,但是老的空间仍然存在)
会开辟一个存储“abc”的内存,还会开辟一个存储“abcdef”的内存,并且a指向这个内存。但是“abc”仍然在内存,等待下一次被利用或者垃圾回收。
--使用StringBuffer / StringBuilder类的append方法进行修改(原地修改,以abc为基础,直接扩张为abcdef,这个操作的效率比申请一个新的空间要快一些)
--StringBuffer / StringBuilder的对象都是可变对象
--StringBuffer(同步,线程安全,修改快速),StringBuilder(不同步,线程不安全,修改更快)
Java字符串(4):
--查看StringAppendTest.java比较字符串操作时间性能
--查看StringPassingTest.java和ArgumentPassing.java理解可变对象传参
结果是:
上述三种方法的时间缩减是惊人的。因此,在程序运行当中,如果需要大量的字符串加法操作,建议使用StringBuffer或StringBuilder。
总结:
--不可变对象提高读效率
--不可变对象设计的方法
--字符串append操作速度:StringBuilder > StringBuffer > String