Это Число Неизменное
Я знаю, что это, вероятно, очень глупо, но многие места утверждают, что класс Integer в Java является неизменяемым, но следующий код:
Integer a=3;
Integer b=3;
a+=b;
System.out.println(a);
выполняется без каких-либо проблем, давая (ожидаемый) результат 6. Таким образом, значение a изменилось. Разве это не означает, что целое число изменчиво? Вторичный вопрос и немного оффтопический: "неизменяемые классы не нуждаются в конструкторах копирования". Кто-нибудь может объяснить почему?
10 ответов:
неизменный не означает, что
a
никогда не может равняться другому значению. Например,String
тоже неизменен, но я все еще могу это сделать:String str = "hello"; // str equals "hello" str = str + "world"; // now str equals "helloworld"
так что же там произошло? Так как
String
неизменен, ясноstr
не был изменен. Но теперь это означает что-то другое. Это потому чтоstr
теперь это совершенно новый экземпляр объекта, так же, как вашInteger
есть. Так что значениеa
не мутировал, но был заменен на совершенно новый объект, т. е.new Integer(6)
.
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.
вы можете определить, что объект изменился с помощью
System.identityHashCode()
(лучший способ - использовать plain==
однако это не так очевидно, что ссылка, а не значение изменилось)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
ссылка изменилась.
на первый заданный вопрос,
Integer a=3; Integer b=3; a+=b; System.out.println(a);
целое число является неизменяемым, поэтому то, что произошло выше, " a " изменилось на новую ссылку значения 6. Начальное значение 3 остается без ссылки в памяти (оно не было изменено), поэтому его можно собирать в мусор.
Если это произойдет со строкой, она будет храниться в пуле (в пространстве PermGen) в течение более длительного периода, чем целые числа, поскольку она ожидает иметь ссылки.
да целое число является неизменным.
a-это ссылка, которая указывает на объект. Когда вы запускаете a += 3, это переназначает a для ссылки на новый целочисленный объект с другим значением.
вы никогда не изменяли исходный объект, а указывали ссылку на другой объект.
читайте о разнице между объектами и ссылками здесь.
неизменное не означает, что вы не можете изменить значение переменной. Это просто означает, что любое новое назначение создает новый объект ( назначает ему новую ячейку памяти), а затем ему присваивается значение.
чтобы понять это для себя, выполните целочисленное назначение в цикле ( с целым числом, объявленным вне цикла ) и посмотрите на живые объекты в памяти.
причина, почему конструктор копирования не нужен для неизменяемых объектов-это простой здравый смысл. Поскольку каждое назначение создает новый объект, язык технически уже создает копию, поэтому вам не нужно создавать другую копию.
"неизменяемые классы не нуждаются в конструкторах копирования". Кто-нибудь может объяснить почему?
причина в том, что есть редко любая необходимость копировать (или даже любой момент копирования) экземпляр неизменяемого класса. Копия объекта должна быть "такой же, как" оригинал, и если это то же самое, не должно быть никакой необходимости создавать его.
есть некоторые основные предположения, хотя:
предполагается, что ваше приложение не придает никакого значения идентификатору объекта экземпляров класса.
предполагается, что класс перегружен
equals
иhashCode
чтобы копия экземпляра была "такой же, как" оригинал ... согласно этим методам.либо одно, либо оба из этих предположений может быть false, и это может потребовать добавления конструктора копирования.
вот как я понимаю неизменяемый
int a=3; int b=a; b=b+5; System.out.println(a); //this returns 3 System.out.println(b); //this returns 8
Если int может мутировать, "a" будет печатать 8, но это не так, потому что он неизменен, вот почему это 3. Ваш пример-это просто новое задание.
Я могу ясно показать, что целое число (и другие его символы, такие как Float, Short и т. д.) неизменяемы простым примером кода:
Пример Кода
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
Это показывает объект, созданный i в main не изменяется, тогда как SB изменяется.
поэтому StringBuilder продемонстрировал изменчивое поведение, но не целое число.
таким образом, целое число является неизменяемым. Отсюда И Доказал
другой код без Только целого числа:
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; } }
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 }
вывод :
Привет Пока Одна тысяча Пять тысяч Одна тысяча Пять тысяч д а
таким образом , char является изменяемым, строковое целое число и int неизменяемы.