なぜJavaのクラスはabstractとfinalを同時に宣言できないのか?
抽象クラス(abstract class)とは
抽象クラスとは、0個以上の抽象メソッドを持つクラスのことです。クラス内に1つでも抽象メソッドが存在する場合は、そのクラスを必ずabstractとして宣言しなければなりません。
抽象クラス内の具象メソッド(実装済みメソッド)を使用したい場合は、まずそのクラスを継承し、抽象メソッドがあればすべて実装した上で、サブクラスのオブジェクトを通じて目的のメソッドを呼び出します。
コード例
次のJavaプログラムでは、抽象クラスMyClassがdisplayという名前の具象メソッドを持っています。
別のクラス(AbstractClassExample)からMyClassを継承し、サブクラスのオブジェクトを使って具象メソッドdisplayを呼び出しています。
abstract class MyClass {
public void display() {
System.out.println("This is a method of abstract class");
}
}
public class AbstractClassExample extends MyClass {
public static void main(String args[]) {
new AbstractClassExample().display();
}
}
実行結果
This is a method of abstract class
finalクラスとは
クラスをfinalとして宣言すると、そのクラスは継承(拡張)できなくなります。finalクラスを継承しようとすると、コンパイル時に「cannot inherit from final SuperClass」というエラーが発生します。
コード例
次のJavaプログラムでは、SuperClassという名前のfinalクラスを定義し、別のクラス(SubClass)から継承しようとしています。
final class SuperClass {
public void display() {
System.out.println("This is a method of the superclass");
}
}
コンパイルエラー
このプログラムをコンパイルすると、以下のようなコンパイルエラーが発生します。
SubClass.java:7: error: cannot inherit from final SuperClass
public class SubClass extends SuperClass{
^
1 error
abstractとfinalを同時に指定できない理由
abstractを指定したクラスは、利用するために必ず継承する必要があります。一方、finalを指定したクラスは継承することができません。
この2つの修飾子は互いに矛盾する性質を持っているため、1つのクラスにabstractとfinalを同時に宣言することはできません。無理に両方を指定すると、コンパイル時エラーが発生します。
コード例
public final abstract class Example {
public void sample() {
}
}
コンパイルエラー
Example.java:1: error: illegal combination of modifiers: abstract and final
public final abstract class Example {
^
1 error
-
なぜJavaのStringクラスは不変(イミュータブル)かつfinalとして設計されているのか?
Stringが不変(イミュータブル)であるとは?JavaにおいてStringクラスが「不変(immutable)」であるということは、オブジェクトそのものの状態を後から変更できないことを意味します。ただし、オブジェクトを参照する変数(参照先)は別のオブジェクトに差し替えることが可能です。また、Stringクラスがfinalとして宣言されているのは、他のクラスによる継承を禁止し、この不変性を破壊されるのを防ぐためです。もし継承が許されていれば、サブクラスで挙動を上書きされ、Stringの安全性が損なわれてしまいます。では、なぜJavaの設計者はStringを不変にしたのでしょうか?主な理由は以下
-
Javaのfinalクラスとは?継承を禁止する仕組みと使い方を徹底解説
Javaにおいて、クラスにfinal修飾子を付けて宣言する最大の目的は、そのクラスがサブクラス化(継承)されることを防ぐことです。クラスがfinalとして宣言されると、どのクラスもそのクラスを継承できなくなり、finalクラスの機能や振る舞いを拡張・変更することが不可能になります。finalクラスの基本構文finalクラスの宣言は非常にシンプルです。クラス名の前にfinalキーワードを付けるだけです。public final class Test { // クラスの本体 }このように宣言されたTestクラスに対して、以下のような継承を試みるとコンパイルエラーが発生します。// コンパイ