Final およびその他の Java キーワード - 1

「こんにちは、アミーゴ!」

「こんにちは、ビラーボ!」

「今日は Java のいくつかのキーワードについて説明します。しかし、最も興味深いキーワード、final から始めます。

「変数、メソッド、またはクラスを宣言するときに、キーワードFinalを使用できます。」

「では、なぜファイナルが必要なのでしょうか?」

「とても簡単です。変数をfinalとしてマークすると、その変数は変更できなくなります。」

final int i = 5;
i++; //Compilation error: the value of i cannot be changed.

"そうか。"

「メソッドをfinalとしてマークすると、派生クラスでメソッドをオーバーライドすることは禁止されます。」

class Cat
{
 public final String getName()
 {
  return "cat";
 }
}

class Tiger extends Cat
{
 public String getName() //Compilation error: overriding the getName()
 {
  return "tiger";
 }
}

「なるほど。でも、なぜメソッドのオーバーライドを禁止する必要があるのでしょうか?」

「例として、プログラマがメソッド内に多くの重要なコードを記述し、そのクラスを継承するすべてのクラスが指定された動作をすることを保証したいとします。」

そして最後に3つ目の使い方です。

「クラスにキーワードfinalをマークすると、そのクラスは継承できなくなります。」

public final class Cat
{
 public String getName()
 {
  return "cat";
 }
}

class Tiger extends Cat //Compilation error: the Cat class cannot be
{
 public String getName()
 {
  return "tiger";
 }
}

「では、なぜクラスの継承を防ぐのでしょうか?」

「煩わしいために継承を妨げているのではなく、セキュリティとコードの整合性を保つためであることを理解してください。クラスの継承が禁止されていない場合、それは許可されているという意味になります。そして、クラスの継承によって記述されたコードは、デザイナーは、このクラスのオブジェクトだけでなく、派生クラスのオブジェクトでも適切に動作します。」

「しかし、開発者が、クラスに小さな変更を加えただけで、すべてが期待どおりに動作しなくなることに気づいた場合は、継承を禁止した方がよいでしょう。」

「たとえば、String クラスは、すべてのプリミティブ型 (Integer、Boolean、Double、Character…) と同様に、final として宣言されます。」

「ああ、分かった。String クラスは不変クラスとして作成されたので、突然変更可能になると、多くのことが機能しなくなります。」

「まあ、ほとんどです。このように言いましょう。すべてが以前とほぼ同じように機能しますが、場合によっては、見つけて理解するのが非常に難しいエラーが発生することがあります。したがって、場合によっては、クラスやメソッドの継承は実際には罪ではありません。しかし、それを禁止すると、後で発見されるエラーが少なくなります。」

「ファイナルを他に使える場所はどこですか?」

「final は関数パラメータの前、メソッド内の変数の前に使用できます。例を次に示します。」

public void setName(final String name)
{
 final String displayName = "Mr."+ name;
  …
 this.name = displayName;
}

「それで、それは何の意味があるのですか?」

「そうですね、2 つあります。まず、この値が単なる変数ではなく特定の定数であることを他の開発者に伝えたい場合は、変数を Final として宣言します。」

たとえば、価格に基づいて消費税を計算したいとします。

public int getPriceNDS()
{
 final int NDS = 20;
 return this.price * NDS / 200;
}

「そして第 2 に、ローカルまたは匿名の内部クラスを作成するときに、このタイプの変数が必要になります。これらのタイプのクラスについては、すぐに説明します。ただし、今日は説明しません。」

「わかりました、これまでのところ、それほど複雑なことは何もありません。」

「変更できなくなるのは変数だけであり、変数が参照するオブジェクトは変更できなくなることに注意してください。オブジェクトは引き続き変更できます。」

「実はそれについて聞こうと思っていたんです。オブジェクトを変更不可能にする方法はないんですか?」

「いいえ、不変クラスを作成しない限り。」

「最終変数の値は変更できないため、すぐに初期値を割り当てる必要があることに注意してください。」

このコードはコンパイルされます このコードはコンパイルできません
class Home
{
 private final int width = 200;
 private final int height = 100;

 public Home()
 {
 }
}
class Home
{
 private final int width;
 private final int height;

 public Home()
 {
 }
}

「とはいえ、Java ではクラスの最終変数の初期化をコンストラクターまで遅らせることができます。」

このコードはコンパイルされます このコードはコンパイルできません
class Home
{
 private final int width = 200;
 private final int height;

 public Home()
 {
  height = 100;
 }
}
class Home
{
 private final int width;
 private final int height;

 public Home()
 {
  height = 100;
 }
}

「さらに、異なるコンストラクターは最終変数を異なる値で初期化できます。これは非常に便利です。」

このコードはコンパイルされます
class Home
{
 private final int width;
 private final int height;

 public Home()
 {
  height = 100;
  width = 200;
 }

 public Home(int width)
 {
  this.height = 300;
  this.width = width;
 }

 public Home(int width, int height)
 {
  this.height = height;
  this.width = width;
 }
}

「それは本当に興味深いトピックでした。まったくすべてが理にかなっています。ありがとう、ビラーボ!」