Являются ли примитивы Java неизменными?
19845 просмотра
5 ответа
Если метод имеет локальную переменную i
:
int i = 10;
а затем я назначаю новое значение:
i = 11;
Будет ли это выделить новую область памяти? Или просто заменить первоначальное значение?
Значит ли это, что примитивы неизменны?
Автор: fYre Источник Размещён: 13.11.2019 11:51Ответы (5)
61 плюса
Будет ли это выделить новую область памяти? Или просто заменить первоначальное значение?
Java не дает никаких гарантий того, что переменные будут соответствовать областям памяти; например, ваш метод может быть оптимизирован таким образом, который i
хранится в регистре, или может даже не сохраняться вообще, если компилятор может увидеть, что вы фактически никогда не используете его значение, или если он может проследить через код и используйте соответствующие значения напрямую.
Но отложим это в сторону. , , если мы возьмем здесь абстракцию за то, что локальная переменная обозначает ячейку памяти в стеке вызовов, то i = 11
просто изменим значение в этой ячейке памяти. Ему не нужно будет использовать новую ячейку памяти, потому что переменная i
была единственной ссылкой на старое местоположение.
Значит ли это, что примитивы неизменны?
Да и нет: да, примитивы неизменны, но нет, это не из-за вышеизложенного.
Когда мы говорим, что что-то является изменчивым, мы имеем в виду, что оно может быть видоизменено: изменено, сохраняя при этом ту же идентичность. Например, когда вы отращиваете волосы, вы мутируете сами: вы все еще вы, но один из ваших атрибутов отличается.
В случае примитивов все их атрибуты полностью определяются их идентичностью; 1
всегда означает 1
, несмотря ни на что, и 1 + 1
всегда 2
. Вы не можете это изменить.
Если данная int
переменная имеет значение 1
, вы можете изменить его на значение 2
вместо этого, но это полное изменение идентичности: оно больше не имеет того значения, которое было раньше. Это похоже на изменение, me
чтобы указать на кого-то другого, а не на меня: это на самом деле не меняет меня , это просто меняется me
.
С объектами, конечно, вы часто можете делать и то, и другое:
StringBuilder sb = new StringBuilder("foo");
sb.append("bar"); // mutate the object identified by sb
sb = new StringBuilder(); // change sb to identify a different object
sb = null; // change sb not to identify any object at all
В общем, оба они будут описаны как «изменяющиеся sb
», потому что люди будут использовать « sb
» как для ссылки на переменную (которая содержит ссылку), так и на объект, на который она ссылается (когда он ссылается на единицу). Такая раскованность хороша, если вы помните различие, когда оно имеет значение.
7 плюса
Immutable
означает, что при каждом изменении значения и объекта для него в стеке создается новая ссылка. Вы не можете говорить об неизменности в случае примитивных типов, только неизменяемы классы Wrapper. Java использует copy_by_value
не по ссылке.
Не имеет значения, передаете ли вы примитивные или ссылочные переменные, вы всегда передаете копию битов в переменной. Таким образом, для примитивной переменной вы передаете копию битов, представляющих значение, а если вы передаете переменную ссылки на объект, вы передаете копию битов, представляющих ссылку на объект.
Например, если вы передаете переменную int со значением 3, вы передаете копию битов, представляющих 3.
После того, как примитив был объявлен its primitive type can never change
, хотя его значение может измениться.
1 плюс
Это не полный ответ, но это способ доказать неизменность значений примитивного типа.
Если примитивные значения (литералы) являются изменяемыми, то следующий код будет работать нормально:
int i = 10; // assigned i the literal value of 10
5 = i; // reassign the value of 5 to equal 10
System.out.println(5); // prints 10
Конечно, это не правда.
Целочисленные значения, такие как 5, 10 и 11, уже сохранены в памяти. Когда вы устанавливаете переменную, равную одному из них: она меняет значение в слоте памяти, где i
находится.
Вы можете увидеть это здесь через байт-код для следующего кода:
public void test(){
int i = 10;
i = 11;
i = 10;
}
Bytecode:
// access flags 0x1
public test()V
L0
LINENUMBER 26 L0
BIPUSH 10 // retrieve literal value 10
ISTORE 1 // store it in value at stack 1: i
L1
LINENUMBER 27 L1
BIPUSH 11 // same, but for literal value 11
ISTORE 1
L2
LINENUMBER 28 L2
BIPUSH 10 // repeat of first set. Still references the same literal 10.
ISTORE 1
L3
LINENUMBER 29 L3
RETURN
L4
LOCALVARIABLE this LTest; L0 L4 0
LOCALVARIABLE i I L1 L4 1
MAXSTACK = 1
MAXLOCALS = 2
Как вы можете видеть в байт-коде (надеюсь), он ссылается на буквальное значение (пример: 10), а затем сохраняет его в слоте для переменной i
. Когда вы меняете значение i
, вы просто изменяете, какое значение хранится в этом слоте. Сами ценности не меняются, их расположение.
0 плюса
Да, они неизменны. Они абсолютно неизменны.
Там хорошее объяснение утопает в здесь . Это для Go, но то же самое в Java. Или любой другой язык в семье C.
Автор: nes1983 Размещён: 03.08.2013 09:070 плюса
Примитивные литералы и final
примитивные переменные неизменны. Не final
примитивные переменные изменчивы.
Идентификацией любой примитивной переменной является имя этой переменной, и очевидно, что такая идентичность неизменна.
Автор: Rostislav Krasny Размещён: 09.09.2018 09:00Вопросы из категории :
- java В чем разница между int и Integer в Java и C #?
- java Как я могу определить IP моего маршрутизатора / шлюза в Java?
- java Каков наилучший способ проверки XML-файла по сравнению с XSD-файлом?
- java Как округлить результат целочисленного деления?
- java Преобразование списка <Integer> в список <String>
- java Почему я не могу объявить статические методы в интерфейсе?
- java Библиотека Java SWIFT
- java Выключение компьютера
- java Как я могу воспроизвести звук на Java?
- java Когда выбирать отмеченные и непроверенные исключения
- primitive Преобразование общего типа из строки
- primitive Примитивный тип 'short' - приведение в Java
- primitive Вектор Java или ArrayList для примитивов
- primitive Нарисуйте многоугольник в C
- primitive Почему Java Generics не поддерживает примитивные типы?
- primitive Вопрос о методах примитивных типов Java
- primitive Passing enums through aidl interfaces
- primitive Почему люди все еще используют примитивные типы в Java?
- primitive Обнаружение повторяющихся значений в примитивном массиве Java
- primitive Как сделать класс, присваиваемый примитивам? Или как мне сделать скалярный класс?