我知道這可能是非常愚蠢的,但是要求很多地方,在Java的Integer類是不可變的,但下面的代碼:是整數永恆
Integer a=3;
Integer b=3;
a+=b;
System.out.println(a);
執行沒有給予任何麻煩(預期)結果6.如此有效地改變了a的值。這不是說Integer是可變的嗎? 第二個問題和一些小題目:「不可變類不需要拷貝構造函數」。任何人都在意解釋爲什麼?
我知道這可能是非常愚蠢的,但是要求很多地方,在Java的Integer類是不可變的,但下面的代碼:是整數永恆
Integer a=3;
Integer b=3;
a+=b;
System.out.println(a);
執行沒有給予任何麻煩(預期)結果6.如此有效地改變了a的值。這不是說Integer是可變的嗎? 第二個問題和一些小題目:「不可變類不需要拷貝構造函數」。任何人都在意解釋爲什麼?
不可變並不意味着a
永遠不能等於另一個值。例如,String
是不可改變的,但我卻仍然可以這樣做:
String str = "hello";
// str equals "hello"
str = str + "world";
// now str equals "helloworld"
到底發生了什麼呢?由於String
是不可變的,因此明確str
未被更改。但它現在等於不同的東西。這是因爲str
現在是一個完全新實例化的對象,就像你的Integer
一樣。所以a
的值沒有變化,但它被一個全新的對象取代,即new Integer(6)
。
「這是因爲str現在是一個完全新實例化的對象」。或者,相反,str(varibale)_points_指向一個新的對象。對象本身不可變,但由於變量不是最終的,它可以指向不同的對象。 – Sandman 2011-04-06 07:20:52
是的,它指向由'+ ='操作實例化的另一個對象。 – 2011-04-06 12:20:44
嚴格地說,它*不需要*是一個*新*對象。拳擊使用'Integer.valueOf(int)',該方法維護'Integer'對象的緩存。所以'Integer'變量上'+ ='的結果可能是之前存在的一個對象(或者它甚至可以是同一個對象......在'a + = 0'的情況下)。 – 2012-05-01 01:11:52
a
是「參考」,以一些整數(3),你的速記a+=b
真正意義做到這一點:
a = new Integer(3 + 3)
所以,不,整數是不可變的,而是指向它們的變量是*。
*很可能有一成不變的變量,這些用關鍵字final
,這意味着基準可能不會改變表示。
final Integer a = 3;
final Integer b = 3;
a += b; // compile error, the variable `a` is immutable, too.
不可變並不意味着您不能更改變量的值。這只是意味着任何新的任務都會創建一個新對象(爲其分配一個新的內存位置),然後將值分配給它。
要了解自己這一點,在一個循環中執行整數分配(與循環外部聲明整數),並期待在內存中的活動對象。
複製構造函數不需要不可變對象的原因很簡單。由於每個作業都會創建一個新對象,因此該語言在技術上已經創建了一個副本,因此您不必創建另一個副本。
是整數是不可變的。
A是指向一個對象的引用。當你運行一個+ = 3時,它重新賦值A來引用一個新的Integer對象,並使用不同的值。
您從未修改原始對象,而是指向不同對象的引用。
閱讀對象和引用here之間的差異。
「不可改變的類不需要拷貝構造函數」。任何人都在意解釋爲什麼?
的原因是,有很少任何需要複製(或複製甚至沒有任何一點),一個不可改變的類的實例。對象的副本應該與原來的「一樣」,如果相同,則不需要創建它。
有一些基本的假設,但:
它假定您的應用程序不放在類的實例的對象標識任何意義。
它假定該類已經超載equals
和hashCode
,以便根據這些方法實例的副本與原始副本相同。
任何一個或兩個這些假設的可能是假的,也可以擔保的另外一個拷貝構造函數。
您可以確定該對象已使用System.identityHashCode()
改變(一個更好的辦法是使用純==
但其並不明顯,與其值已更改參考)
Integer a = 3;
System.out.println("before a +=3; a="+a+" id="+Integer.toHexString(System.identityHashCode(a)));
a += 3;
System.out.println("after a +=3; a="+a+" id="+Integer.toHexString(System.identityHashCode(a)));
打印
before a +=3; a=3 id=70f9f9d8
after a +=3; a=6 id=2b820dda
你可以看到對象a
的底層「id」指已經改變。
System.identityHashCode()是一個非常好的提示。謝謝你。 – 2017-03-24 12:50:55
要問最初的問題,
Integer a=3;
Integer b=3;
a+=b;
System.out.println(a);
Integer是不變的,所以什麼事情上面是「A」變爲價值6.新的參考初始值3留在沒有參考內存(它沒有被改變),所以它可以被垃圾回收。
如果發生這種情況的字符串,它會保留在池中(在PermGen空間中)比整數更長的時間段,因爲它期望有引用。
我可以明確指出的整數(和其他的信條一樣浮的,短片等)都是通過簡單的示例代碼不變:
示例代碼
public class Test{
public static void main(String... args){
Integer i = 100;
StringBuilder sb = new StringBuilder("Hi");
Test c = new Test();
c.doInteger(i);
c.doStringBuilder(sb);
System.out.println(sb.append(i)); //Expected result if Integer is mutable is Hi there 1000
}
private void doInteger(Integer i){
i=1000;
}
private void doStringBuilder(StringBuilder sb){
sb.append(" there");
}
}
實際結果
結果涉及到他您好有100(在兩個SB的情況下,和i是可變對象),而不是預期的結果您好有1000
這表明通過我在主創建的對象沒有被修改,而sb被修改。
所以StringBuilder演示了可變行爲但不是整數。
因此Integer是不可變的。因此,事實證明
另一個不只是整數代碼:
public class Test{
public static void main(String... args){
Integer i = 100;
Test c = new Test();
c.doInteger(i);
System.out.println(i); //Expected result is 1000 in case Integer is mutable
}
private void doInteger(Integer i){
i=1000;
}
}
你正在做兩件不同的事情 - 試圖重新分配整數並在stringbuilder上調用一個方法。如果你做'private void doStringBuilder(StringBuilder sb){sb = new StringBuilder(); }'然後'sb'不變。 – MT0 2016-04-04 08:10:42
我添加了StringBuilder(這是可變的),以便將Integer與另一個可變對象並置。如果你想要的話,你可以刪除所有與StringBuilder相關的代碼,只需打印出我看到100. – 2016-04-04 08:20:28
@ MT0添加了極簡代碼供您參考。 – 2016-04-04 08:23:47
這是我的理解不變
int a=3;
int b=a;
b=b+5;
System.out.println(a); //this returns 3
System.out.println(b); //this returns 8
如果INT可能會變異, 「一」 將打印8但它並不是因爲它是不可變的,所以它是3.你的例子只是一個ne分配。
public static void main(String[] args) {
// TODO Auto-generated method stub
String s1="Hi";
String s2=s1;
s1="Bye";
System.out.println(s2); //Hi (if String was mutable output would be: Bye)
System.out.println(s1); //Bye
Integer i=1000;
Integer i2=i;
i=5000;
System.out.println(i2); // 1000
System.out.println(i); // 5000
int j=1000;
int j2=j;
j=5000;
System.out.println(j2); // 1000
System.out.println(j); // 5000
char c='a';
char b=c;
c='d';
System.out.println(c); // d
System.out.println(b); // a
}
輸出是:
嗨 再見 千千 d 一個
所以焦炭是可變的,字符串整數和INT是不可改變的。
此答案不提供任何其他信息。 – 2017-10-09 12:51:39
該類是不可變的,但自動裝箱正在發生時髦的事情發生:http://stackoverflow.com/questions/3085332/comparison-between-variables-pointing-to-same-integer-object – birryree 2011-04-06 00:31:19
謝謝,拳擊是關鍵字我需要谷歌:) – 2011-04-06 00:37:52
你正在混淆不變值與最終值或常量值。 – 2013-08-14 06:43:03