Это Число Неизменное


Я знаю, что это, вероятно, очень глупо, но многие места утверждают, что класс Integer в Java является неизменяемым, но следующий код:

Integer a=3;
Integer b=3;
a+=b;
System.out.println(a);

выполняется без каких-либо проблем, давая (ожидаемый) результат 6. Таким образом, значение a изменилось. Разве это не означает, что целое число изменчиво? Вторичный вопрос и немного оффтопический: "неизменяемые классы не нуждаются в конструкторах копирования". Кто-нибудь может объяснить почему?

10 85

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 неизменяемы.