Javaのコンテキストで次の行の意味を教えてください。
最終変数は、不変でなければ操作できます
私の知る限り、変数をfinalとして宣言することで、それを再び変更することはできません。その場合、上記の行でimmutableとはどういう意味ですか?
最終変数が参照型(つまり、intのようなプリミティブではない)の場合、変更できないのは参照のみであることを意味します。別のオブジェクトを参照することはできませんが、クラスが許可している場合、参照するオブジェクトのフィールドは変更できます。例えば:
final StringBuffer s = new StringBuffer();
StringBufferの内容は引き続き任意に変更できます。
s.append("something");
しかし、あなたは言うことができません:
s = null;
または
s = anotherBuffer;
一方:
final String s = "";
文字列は不変です-文字列を変更できるメソッドはありません(Reflectionを使用して地獄に行く場合を除く)。
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");
Lへの最初の割り当ての後。ただし、これを実行できることに注意してください。
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が宣言されたときに、nullでもないものには割り当てられないため、実行できます。そのため、何かを一度だけ割り当てることができます。
プリミティブについても同じことが言えます。次のように値を割り当てることができます。
class Test1 {
public static void main(String[] args) {
final int i;
i = 2;
}
}
しかし、プリミティブ型に対してできることは値を割り当てることだけなので、これ以上操作することはできません。
最終変数が参照するオブジェクトまたは値を変更することはできません。最終変数は1回しか割り当てることができません。
これは、オブジェクトの状態を変更できるかどうかには影響しません。オブジェクト自体は、この操作が禁止されるような方法でコーディングされていない限り、引き続き操作できます。不変オブジェクトとは、状態を変更できないオブジェクトです。
他の人が言ったように、それは変数が指すオブジェクトを操作できることを意味しますが、参照を変更することはできません(つまり、変数に別のオブジェクトを割り当てます)。
List
などの設計によって変更可能なオブジェクトは変更できます(要素を追加できます)が、String
やInteger
などの不変オブジェクトがある場合変更することはできません(クラスString
がサポートするすべての操作は新しいインスタンスを返し、実際のオブジェクトを変更しないでください)。
たとえば、可変の最終変数を操作できます。 StringBuffer型ですが、不変型のfinal変数を操作することはできません。
可変変数の場合、値が変更されるたびに新しいオブジェクトが作成されるわけではありません。ただし、不変型の場合、値を変更するたびに新しいオブジェクトが作成されるため、最終オブジェクトを作成するときに変更することはできません。
参照が指しているオブジェクトの状態をメソッドで変更できる場合でも、そのメソッドを呼び出すことができます。例えば
final MyClass myClass = new MyClass();
myClass.setVar(something);
myClass
自体は変更されていないため、つまり、myClass = myClass1;
。
はい、最終変数は変更できます。
final StringBuffer s = new StringBuffer();
// won't work
s = new StringBuffer();
//this works
s.append("hai");
参照を変更することはできませんが、オブジェクトのフィールドは変更できます。 詳細
いつも私を殺すもの?
最終変数を思ったほど安全にしたい場合は、String []のコピーを返すために多くの追加コードが必要です。