Окончательная обработка переменных в Java - PullRequest
45 голосов
/ 09 августа 2009

Может ли кто-нибудь сказать мне, что означает следующая строка в контексте Java:

конечная переменная все еще может быть манипулировать, если он не является неизменным

Насколько я знаю, объявив любую переменную как окончательную, вы не сможете изменить ее снова, тогда что они означают со словом immutable в строке выше?

Ответы [ 9 ]

98 голосов
/ 09 августа 2009

Это означает, что если ваша последняя переменная является ссылочным типом (т.е. не примитивом типа int), то это только ссылка, которая не может быть изменена. Он не может быть сделан для ссылки на другой объект, но поля объекта, на который он ссылается, все еще могут быть изменены, если класс позволяет это. Например:

final StringBuffer s = new StringBuffer();

Содержимое StringBuffer все еще может быть произвольно изменено:

s.append("something");

Но вы не можете сказать:

s = null;

или

s = anotherBuffer;

С другой стороны:

final String s = "";

Строки являются неизменяемыми - просто не существует метода, который позволил бы вам изменить строку (если вы не используете Reflection - и не попадете в ад).

16 голосов
/ 09 августа 2009

Если у вас есть окончательная ссылка на объект Java, вы все равно можете манипулировать им, но не можете изменить его ссылку. Например, этот код совершенно легален:

import javax.swing.JLabel;

class Test1 {
    private final static JLabel l = new JLabel("Old text");
    public static void main(String[] args) {
        System.err.println(l.getText());
        l.setText("New Text");
        System.err.println(l.getText());
    }
}

Но вы не можете сказать:

l = new JLabel("Newest Text");

После первого присвоения л. Обратите внимание, что вы можете сделать это, хотя:

import javax.swing.JLabel;

class Test1 {
    public static void main(String[] args) {
        final JLabel l;
        String s = getArbitaryString(); // Assume this method returns a string
        l = new JLabel(s);
        System.err.println(l.getText());
    }
}

Это может быть сделано, потому что когда l объявлено, оно не присваивается ничему, даже нуль. Таким образом, вы можете назначить что-то на это только один раз.

То же самое относится и к примитивам. Вы можете присвоить ему значение следующим образом:

class Test1 {
    public static void main(String[] args) {
        final int i;
        i = 2;
    }
}

Но теперь вы не можете манипулировать им дальше, поскольку единственное, что вы можете сделать для примитивных типов, - это присвоить им значения.

4 голосов
/ 09 августа 2009

Вы не можете изменить объект или значение, на которое ссылается последняя переменная. Вы можете назначить окончательную переменную только один раз.

Это не влияет на возможность изменения состояния объекта. С самим объектом все еще можно манипулировать, если он не закодирован таким образом, что эта манипуляция запрещена. Неизменяемый объект - это объект, состояние которого не может измениться.

3 голосов
/ 09 августа 2009

Как уже говорили другие, это означает, что вы можете манипулировать объектом, на который указывает переменная, но вы не можете изменить ссылку (то есть назначить другой объект переменной).

Объекты, которые являются изменяемыми по конструкции, такие как List, можно изменить (вы можете добавить к ним элементы), тогда как, если у вас есть неизменяемый объект, такой как String или Integer, вы не сможете чтобы изменить его (все операции, поддерживаемые классом String, возвращают новый экземпляр и не изменяют фактический объект).

0 голосов
/ 23 февраля 2015

Да, последняя переменная может быть изменена.

    final StringBuffer s = new StringBuffer();
    // won't work
    s = new StringBuffer();
    //this works
    s.append("hai");

Вы не можете изменить ссылку, но поля объекта могут быть изменены. для более подробной информации

0 голосов
/ 23 августа 2012

Вы можете манипулировать изменяемыми конечными переменными, например, типа StringBuffer, но вы не можете манипулировать конечными переменными неизменяемых типов.

В случае непостоянных переменных новый объект не создается каждый раз, когда изменяется его значение. Но в случае неизменяемых типов, когда вы изменяете значение, создается новый объект, поэтому, когда вы делаете его окончательным, вы не можете его изменить.

0 голосов
/ 27 февраля 2010

Тот, который всегда убивает меня?

Если вы хотите, чтобы конечные переменные были действительно такими же безопасными, как вы думали, вам нужно много дополнительного кода, чтобы вернуть копию строки [].

0 голосов
/ 27 февраля 2010

Вы можете вызвать любой метод для него, даже если метод может изменить состояние объекта, на который указывает ссылка. * 1001 например *

final MyClass myClass = new MyClass();
myClass.setVar(something);

Это нормально, потому что myClass само не меняется, т.е. вы не делаете myClass = myClass1;.

0 голосов
/ 09 августа 2009

Вы все еще можете изменить 'окончательную' переменную, используя Reflection.

...