定数

「アミーゴ、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変数名の前は、その変数への変更に対する単なる保護です。変数にオブジェクトへの参照が格納されている場合、そのオブジェクトは引き続き変更される可能性があります。」

「よくわかりません。」

「すぐに理解できるでしょう。例を示します。

final int[] data = {1, 2, 3, 4, 5, 6};

data = {6, 7, 8, 9};

data[0] = 0;
data[1] = 0;
data[2] = 0;
配列を作成します。

これは許可されません。変数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 つのメソッド内で同じ名前の複数のローカル変数を作成することはできません。別のメソッドでは作成できます。」

"そんなこと知ってる!"

「しかし、おそらくあなたが知らないのは、クラス内の変数とメソッド内のローカル変数が同じ名前を持つ可能性があるということです。

例:

コード 可変可視性
public class Solution
{
   public int count = 0;
   public int sum = 0;

   public void add(int data)
   {
     sum = sum + data;
     int sum = data * 2;
     count++;
   }
}

count, sum
count, sum
count, sum
count, sum
count, sum
count, sum, data
count, sum, data
count, sum, data
count, sum, data
count, sum

addメソッド内で、 という名前のローカル変数を宣言しましたsum。メソッドが終了するまで、インスタンス変数をシャドウ (またはマスク)しますsum。」

「うーん...ある意味、これは予想通りの動作だと思います。」

this「しかし、話はこれで終わりではありません。インスタンス変数がローカル変数によってシャドウされている場合でも、メソッド内でインスタンス変数を参照する方法がまだあることがわかりました。これを行うには、名前の前にキーワードを記述します。:

this.name

「名前の競合が正常に解決された例を次に示します。

コード 可変可視性
public class Solution
{
   public int count = 0;
   public int sum = 0;

   public void add(int data)
   {
     int sum = data * 2;
     this.sum = this.sum + data;
     count++;
   }
}

this.count, this.sum
this.count, this.sum
this.count, this.sum
this.count, this.sum
this.count, this.sum
this.count, this.sum, data
this.count, this.sum, data, sum
this.count, this.sum, data, sum
this.count, this.sum, data, sum
this.count, this.sum

countおよび変数は、キーワードのsum有無にかかわらず、どこでも使用できますthissumローカル変数がインスタンス変数をシャドウする行ではsum、キーワードsumを使用してのみインスタンス変数にアクセスできますthis

「もちろん、これは練習する必要があります。」

「君ならなんとかなるよ。」

「単なる (非静的) インスタンス変数ではなく、静的クラス変数がシャドウされている場合はどうなりますか? 経由でアクセスすることはできませんthis。」

「そうです。this キーワードは機能しません。クラス名を通じて参照する必要があります。

ClassName.name

例:

コード 可変可視性
public class Solution
{
   public static int count = 0;
   public static int sum = 0;

   public void add(int data)
   {
     int sum = data * 2;
     Solution.sum = Solution.sum + data;
     count++;
   }
}

Solution.count, Solution.sum
Solution.count, Solution.sum
Solution.count, Solution.sum
Solution.count, Solution.sum
Solution.count, Solution.sum
Solution.count, Solution.sum, data
Solution.count, Solution.sum, data, sum
Solution.count, Solution.sum, data, sum
Solution.count, Solution.sum, data, sum
Solution.count, Solution.sum

「注意してください:クラス名をプレフィックスとして使用してもしなくても、どこでも 静的変数countと静的変数にアクセスできます。ローカル変数がインスタンス変数をシャドウしている行では、クラス変数へのアクセスはプレフィックスとして使用している場合にのみ可能です。sumSolutionsumsumsumSolution

forループ内の変数

「そして、小さいながらも興味深い事実がもう 1 つあります。変数が特別な方法で宣言されている場所もあります。これはループ内について話していますfor」通常、forループには括弧内に変数が含まれますcounter。そして、この変数の可視性はどうなるでしょうか? 結局のところ、それはループの本体にはありません。それは全体のメソッドですか?か否か?"

for「これについてはすでに聞いたことがあります。私が理解しているところによると、ループのヘッダーで宣言された変数は、ループの本体ループのヘッダーforでのみ表示されます。」

「よくやった、アミーゴ。それでも、この内容を補強する例を見てください。

コード 可変可視性
public static void main(String[] args)
{
   int a = 0;

   for (int i = 0; i < 10; i++)
   {
     System.out.println(i);
   }

   System.out.println("end");
}


a
a
a, i
a, i
a, i
a
a
a

「つまり、私のコードでは、同じ名前のカウンター変数を使用して複数のループを次々に記述でき、問題は発生しないということですか?」

「問題はないでしょう。ほら、見てください。

コード 可変可視性
public static void main(String[] args)
{
   int a = 0;

   for (int i = 0; i < 10; i++)
   {
     System.out.println(i);
   }

   for (int i = 0; i < 10; i--)
   {
     System.out.println(i);
   }

   System.out.println("end");
}


a
a
a, i
a, i
a, i
a
a
a, i
a, i
a, i
a
a
a