java 不可变类型
2015-01-03 16:45
155 查看
1. java不可变性初探
我们先看下面一个例子:代码如下:import java.math.BigInteger; public class BigProblem { public static void main(String[ ] args) { BigInteger fiveThousand = new BigInteger("5000"); BigInteger fiftyThousand = new BigInteger("50000"); BigInteger fiveHundredThousand = new BigInteger("500000"); BigInteger total = BigInteger.ZERO; total.add(fiveThousand); total.add(fiftyThousand); total.add(fiveHundredThousand); System.out.println(total); } }
你可能会认为这个程序会打印出555000。毕竟,它将total设置为用BigInteger表示的0,然后将5,000、50,000和500,000加到了这个变量上。如果你运行该程序,你就会发现它打印的不是555000,而是0。很明显,所有这些加法对total没有产生任何影响。
对此有一个很好理由可以解释:BigInteger实例是不可变的。String、BigDecimal以及包装器类型:Integer、Long、Short、Byte、Character、Boolean、Float和Double也是如此,你不能修改它们的值。我们不能修改现有实例的值,对这些类型的操作将返回新的实例。起先,不可变类型看起来可能很不自然,但是它们具有很多胜过与其向对应的可变类型的优势。不可变类型更容易设计、实现和使用;它们出错的可能性更小,并且更加安全[EJ Item 13]。
为了在一个包含对不可变对象引用的变量上执行计算,我们需要将计算的结果赋值给该变量。这样做就会产生下面的程序,它将打印出我们所期望的555000, 代码如下:
package cn.xy.test; public class StringTest { /** * a的值在编译时就被确定下来,故其值"xy"被放入String的驻留池(驻留池在堆中)并被a指向。 * b的值在编译时也被确定,那么b的值在String的驻留池中找是否有等于"xy"的值,有的话也被b指向。 * 故两个对象地址一致 * @return true */ public static Boolean testString1() { String a = "xy"; String b = "xy"; return a == b; } /** * b的值在是两个常量相加,编译时也被确定。 * @return true */ public static Boolean testString2() { String a = "xyy"; String b = "xy" + "y"; return a == b; } /** * b的值为一个变量和一个常量相加,无法编译时被确定,而是会在堆里新生成一个值为"abc"的对象 * @return false */ public static Boolean testString3() { String a = "xyy"; String b = "xy"; b = b + "y"; return a == b; } /** * b的值都无法编译时被确定,而是会在堆里分别新生成一个对象叫"xyy"。 * @return false */ public static Boolean testString4() { String a = "xyy"; String b = "xy".concat("y"); return a == b; } /** * new String()创建的字符串不是常量,不能在编译期就确定,所以new String() 创建的字符串不放入常量池中,它们有自己的地址空间。 * a,b的值都无法编译时被确定,会在堆里分别新生成一个值为"xy"的对象。 * @return fasle */ public static Boolean testString5() { String a = new String("xy"); String b = new String("xy"); return a == b; } /** * intern()把驻留池中"xy"的引用赋给b。 * @return true */ public static Boolean testString6() { String a = "xy"; String b = new String("xy"); b = b.intern(); return a == b.intern(); } /** * char的toString方法返回的是一个char对象的字符串,而不是我们想象的"xy" * @return false */ public static Boolean testString7() { String b = "xy"; char[] a = new char[]{'x','y'}; return a.toString().equals(b); } /** * char是一种新的类型,不存在驻留池的概念。 * @return fasle */ public static Boolean testString8() { String b = "xy"; char[] a = new char[]{'x','y'}; return a.toString() == b; } /** * String不可变性的体现 */ String str = "xy"; public String chage(String str) { str = "xyy"; return str; } /** * 一般引用类型的可变性(传值的时候把地址传过去,相当于把仓库的要是交给方法,方法拿到钥匙去移动仓库里的东西) */ Person p = new Person("xy"); public String changePerson(Person p) { p.setName("xyy"); return p.toString(); } public static void main(String[] args) { print(testString1()); // true print(testString2()); // true print(testString3()); // fasle print(testString4()); // false print(testString5()); // false print(testString6()); // true print(testString7()); // false print(testString8()); // false StringTest t = new StringTest(); print(t.str); // xy print(t.chage(t.str)); // xxy print(t.str); // xy print(t.p.toString()); //xy print(t.changePerson(t.p)); //xyy print(t.p.toString()); //xyy } public static void print(Object o) { System.out.println(o); } }
View Code
参考:
http://www.jb51.net/article/37889.htm
http://www.jb51.net/article/49092.htm
/article/1634168.html
相关文章推荐
- Java中String类型的不可变性和驻留池
- Java String类型值真的不可改变吗?
- java中可变类型和不可变类型
- Java中String类型的不可变性和驻留池
- JAVA String类型不可变
- Java通过反射获取泛型实际类型总结(什么可获取,什么不可获取)
- Java String 设计为不可变类型的好处
- Java String类型值真的不可改变吗?
- The Java™ Tutorials — Generics :Non-Reifiable Types 不可具体化类型
- Java中String类型的不可变性和驻留池
- Java String类型值真的不可改变吗?
- 深入Java不可变类型的详解
- 掌握 Java 泛型类型(一)
- 浅谈Java中的存储空间类型
- Java的简单类型进行精确的浮点数运算
- java中的数据类型转换
- 掌握 Java 泛型类型(三)
- Java中类型转换的特例
- [XMLer的生活]可使用基本类型作为键值的Java集合类-Trove 集合类
- java的类型转换