Java
 Computer >> コンピューター >  >> プログラミング >> Java

Javaの静的メソッドはオーバーロード・オーバーライドできる?違いと注意点をコード例で解説

Javaにおける静的メソッド(staticメソッド)はオーバーロード可能ですが、オーバーライドは不可能です。ただし、オーバーロードにも条件があり、2つのメソッドが「static」キーワードの有無だけでしか違わない場合、それらをオーバーロードすることはできません。

この記事では、静的メソッドのオーバーロードとオーバーライドに関する挙動を、具体的なコード例とともに詳しく解説します。

静的メソッドのオーバーロード

静的メソッドは、引数の型や数が異なれば、同じクラス内で複数定義できます。以下の例を見てみましょう。

public class Demo{
    public static void test(){
        System.out.println("Demoクラスのtest関数が呼び出されました");
    }
    public static void test(int val){
        System.out.println("パラメータ付きDemoクラスのtest関数が呼び出されました");
    }
    public static void main(String args[]){
        System.out.println("mainクラスからDemo関数を呼び出します");
        Demo.test();
        Demo.test(57);
    }
}

出力

mainクラスからDemo関数を呼び出します
Demoクラスのtest関数が呼び出されました
パラメータ付きDemoクラスのtest関数が呼び出されました

コードの解説

「Demo」という名前のクラスには、特定のメッセージを出力する「test」という静的関数が定義されています。さらに、整数値を引数として受け取る同名の「test」関数も定義されており、これがオーバーロードに該当します。main関数では、test関数を引数なしと整数引数付きの両方で呼び出しており、それぞれ対応するメッセージがコンソールに表示されます。

このように、引数リストが異なる限り、静的メソッド同士でも通常のメソッドと同じようにオーバーロードが可能です。

静的メソッドのオーバーライドは不可能

一方、静的メソッドはオーバーライドできません。サブクラスで親クラスと同じシグネチャを持つ静的メソッドを定義すること自体は可能ですが、これはメソッド隠蔽(メソッドハイディング)と呼ばれる別の挙動であり、実行時ポリモーフィズム(動的束縛)にはなりません。したがって、厳密な意味でのオーバーライドは成立しません。以下に例を示します。

class base_class{
    public static void show(){
        System.out.println("基底クラスの静的(クラス)メソッドです");
    }
    public void print_it(){
        System.out.println("基底クラスの非静的(インスタンス)メソッドです");
    }
}
class derived_class extends base_class{
    public static void show(){
        System.out.println("派生クラスの静的(クラス)メソッドです");
    }
    public void print_it(){
        System.out.println("派生クラスの非静的(インスタンス)メソッドです");
    }
}
public class Demo{
    public static void main(String args[]){
        base_class my_instance = new derived_class();
        System.out.println("基底クラス型のインスタンスを作成しました。");
        my_instance.show();
        System.out.println("show関数を呼び出しました");
        my_instance.print_it();
        System.out.println("print_it関数を呼び出しました");
    }
}

出力

基底クラス型のインスタンスを作成しました。
基底クラスの静的(クラス)メソッドです
show関数を呼び出しました
派生クラスの非静的(インスタンス)メソッドです
print_it関数を呼び出しました

コードの解説

基底クラス「base_class」には、メッセージを出力する静的関数「show」と、非静的(インスタンス)関数「print_it」が定義されています。派生クラス「derived_class」は基底クラスを継承し、両方の関数を再定義しています。

main関数では、派生クラスのインスタンスを基底クラス型の変数に代入して生成しています。ここで注目すべき重要なポイントは次の通りです。

  • 静的メソッド「show」を呼び出すと、基底クラス側の処理が実行される
  • 非静的メソッド「print_it」を呼び出すと、派生クラス側の処理が実行される

この違いが生じる理由は、静的メソッドの呼び出しが変数の宣言型(参照の型)に基づいてコンパイル時に解決されるのに対し、インスタンスメソッドの呼び出しは実際のオブジェクトの型に基づいて実行時に解決されるためです。つまり、静的メソッドはポリモーフィズムの対象外であり、これがオーバーライドが不可能である根本的な理由です。

まとめ

  • 静的メソッドは、引数の構成が異なれば同一クラス内でオーバーロードできる
  • ただし、「static」キーワードの有無だけが違いのメソッド同士はオーバーロードできない
  • 静的メソッドはオーバーライドできない。サブクラスで同名の静的メソッドを定義すると、それは「メソッド隠蔽」となる
  • 静的メソッドの呼び出しはコンパイル時に参照型によって解決されるため、実行時ポリモーフィズムは働かない
  1. Javaの列挙型(enum)は任意のクラスを拡張できる?継承の仕組みを解説

    Javaの列挙型(enum)とは列挙型(enum)は、Javaにおいて定数の集合を格納するためのデータ型です。1週間の曜日や1年の月名など、固定された値のグループを扱う際に活用されます。列挙型を定義するには、enumキーワードの後に列挙型の名前を続けて記述します。enum Days { SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY }配列と同様に、列挙型内の要素(定数)には0から始まる番号が自動的に割り当てられます。上記の例では、各曜日が以下の図のように番号で識別されます。列挙型はクラスとよく似た構造を持ち

  2. JavaでJTextFieldにパディングを追加する方法【setMarginの使い方】

    JTextFieldはJTextComponentクラスのサブクラスであり、ユーザーが1行形式でテキストを入力できる、Swingの中でも特に重要なコンポーネントの一つです。JTextFieldでは、ユーザーが入力を行う際にActionListenerインターフェースを通じてアクションイベントが発生します。主なメソッドとしては、setText()、getText()、setBorder()、setEnabled()などが挙げられます。 JTextFieldにパディング(内側の余白)を追加したい場合は、JTextComponentクラスが提供するsetMargin(Insets m)メソッドを使用