定数
「アミーゴ、Java ではすべての変数を変更できるわけではないことをご存知ですか?」
「どうですか、キム?確かに、『変数』という言葉自体が変化を表しています。」
「それについては疑いの余地がありません。他の多くのプログラミング言語と同様に、Java には定数、つまり値を変更できない変数があります。そして、まさに『定数』という言葉が不変性を表しています。」
「それで、それらは何のためにあるのですか?」
「通常、それらは、1 年の月の数Pi
や日数など、ある種の基本的なものに使用されます。とはいえ、原則として、プログラマーは、そうすることを決定すれば、任意の変数を定数にすることができます」だから必要なのよ。」
「名前とか、車の色とか、曜日とか?」
「あなたの考えは正しいです。変更すべきではないものはすべてです。」
「そして、これらの定数は Java ではどのように見えるのでしょうか?」
「Java には、それらのための特別なキーワードがあります。不変変数の作成は、通常の変数の作成と同じように見えます。唯一の違いは、次のように、final
変数の型の前に単語 を記述する必要があることです。final
final Type name = value;
「定数を作成して、それに別の値を代入しようとするとどうなるでしょうか?」
「それは正しい質問です。そして、正しい答えはこれです。変数に別の値を代入しようとすると、final
プログラムはコンパイルできません。」
「final
変数を宣言しても値を代入しなかったらどうなるでしょうか?」
「これを行うことに意味がないので、Java でも許可されていません。変数はfinal
宣言時に初期化する必要があります。つまり、変数に値を代入する必要があります。この規則には例外が 1 つあります。静的クラス変数をコンストラクターに変換します。ただし、それについては後で学びます。
「とはいえ、すべてがfinal
定数であるわけではありません。キーワードの数を減らすために、Java 開発者はこの言葉をfinal
単に定数を宣言するだけでなく、final
メソッドやクラスにも適用できます。として宣言されたメソッドはfinal
オーバーライドできません。また、クラスfinal
継承できないと宣言されました。」
「えっと...上書きされましたか? 継承されましたか? 今何語を話していますか?」
「オブジェクト指向プログラミングの言語です。すぐに理解できるようになります。それまでは、美しい用語を楽しんでください。」
「わかりました。では、final
変数、クラス、メソッドの前に置くことができ、このキーワードはそれらをある意味で不変にすることができますね?」
「はい。さらに、final
修飾子はローカル変数、メソッド パラメーター、クラス フィールド、静的クラス変数などの変数の前に追加できます。
「ここで覚えておくべき重要な点があります。final
変数名の前は、その変数への変更に対する単なる保護です。変数にオブジェクトへの参照が格納されている場合、そのオブジェクトは引き続き変更される可能性があります。」
「よくわかりません。」
「すぐに理解できるでしょう。例を示します。
|
配列を作成します。 これは許可されません。変数 data は として宣言されていますfinal 。しかし、これならできます。 そしてこれも。 |
「分かりました。それは難しいですね。」
グローバル定数
「グローバル定数とは何だと思いますか?」
「グローバル定数はおそらくグローバル変数のようなもので、単なる定数ではないでしょうか?」
「その通りです。プログラム内でグローバル定数を宣言する必要がある場合は、静的クラス変数 を作成し、それらをpublic
と にしますfinal
。そのような変数の名前には特別なスタイルがあります。変数はすべて大文字で書かれ、アンダースコア文字が使用されます。別々の言葉。
例:
class Solution
{
public static final String SOURCE_ROOT = "c:\\projects\\my\\";
public static final int DISPLAY_WIDTH = 1024;
public static final int DISPLAY_HEIGHT = 768;
}
変数のシャドウイング
「前に述べたように、1 つのメソッド内で同じ名前の複数のローカル変数を作成することはできません。別のメソッドでは作成できます。」
"そんなこと知ってる!"
「しかし、おそらくあなたが知らないのは、クラス内の変数とメソッド内のローカル変数が同じ名前を持つ可能性があるということです。
例:
コード | 可変可視性 |
---|---|
|
|
「add
メソッド内で、 という名前のローカル変数を宣言しましたsum
。メソッドが終了するまで、インスタンス変数をシャドウ (またはマスク)しますsum
。」
「うーん...ある意味、これは予想通りの動作だと思います。」
this
「しかし、話はこれで終わりではありません。インスタンス変数がローカル変数によってシャドウされている場合でも、メソッド内でインスタンス変数を参照する方法がまだあることがわかりました。これを行うには、名前の前にキーワードを記述します。:
this.name
「名前の競合が正常に解決された例を次に示します。
コード | 可変可視性 |
---|---|
|
|
count
および変数は、キーワードのsum
有無にかかわらず、どこでも使用できますthis
。sum
ローカル変数がインスタンス変数をシャドウする行ではsum
、キーワードsum
を使用してのみインスタンス変数にアクセスできますthis
。
「もちろん、これは練習する必要があります。」
「君ならなんとかなるよ。」
「単なる (非静的) インスタンス変数ではなく、静的クラス変数がシャドウされている場合はどうなりますか? 経由でアクセスすることはできませんthis
。」
「そうです。this キーワードは機能しません。クラス名を通じて参照する必要があります。
ClassName.name
例:
コード | 可変可視性 |
---|---|
|
|
「注意してください:クラス名をプレフィックスとして使用してもしなくても、どこでも 静的変数count
と静的変数にアクセスできます。ローカル変数がインスタンス変数をシャドウしている行では、クラス変数へのアクセスはプレフィックスとして使用している場合にのみ可能です。sum
Solution
sum
sum
sum
Solution
for
ループ内の変数
「そして、小さいながらも興味深い事実がもう 1 つあります。変数が特別な方法で宣言されている場所もあります。これはループ内について話していますfor
。」通常、for
ループには括弧内に変数が含まれますcounter
。そして、この変数の可視性はどうなるでしょうか? 結局のところ、それはループの本体にはありません。それは全体のメソッドですか?か否か?"
for
「これについてはすでに聞いたことがあります。私が理解しているところによると、ループのヘッダーで宣言された変数は、ループの本体とループのヘッダーfor
でのみ表示されます。」
「よくやった、アミーゴ。それでも、この内容を補強する例を見てください。
コード | 可変可視性 |
---|---|
|
|
「つまり、私のコードでは、同じ名前のカウンター変数を使用して複数のループを次々に記述でき、問題は発生しないということですか?」
「問題はないでしょう。ほら、見てください。
コード | 可変可視性 |
---|---|
|
|
GO TO FULL VERSION