Javaには、オーバーライドと呼ばれる機能が存在します。
既存クラスの一部のメソッドだけを変更して使いたい場合などに使用できる、便利な機能です。
今回の記事では、オーバーライドについての基本的な知識や、具体的な使用方法について解説をしていきたいと思います!
Javaのオーバーライドとは?
オーバーライドとは、継承した親クラス内で既に定義されているメソッドの内容を、子クラス側で再定義することを言います。
親クラス内で定義したメソッドはそのまま子クラスでも使用することができますが、いくつかの条件をクリアすることで、処理内容を子クラス独自のものに変更することができます。
オーバーライドでメソッドの再定義を行っても、親クラスや他の子クラスの処理内容に影響を与えることはありません。
また、メソッドをオーバーライドした場合でも、親クラスのメソッドを呼び出して使用することが可能です。
メソッドのオーバーライドを行う場合は、以下の条件を守る必要があります。
- メソッド名、引数の型・数・順番、戻り値の型が親クラスのメソッドと同じであること
- アクセスレベルが親クラスと同じか、それよりも緩い制限であること
(例:親クラス側がprotectedの場合、子クラス側はpublicかprotectedを指定可能)
その他にもいくつかのルールがありますが、詳しい内容は後ほど説明します。
オーバーライドを使うメリット
オーバーライドを使用するメリットは、主に 「再利用のしやすさ」 と 「保守のしやすさ」 の2つがあります。
Javaを含むオブジェクト指向型のプログラミングには、「ポリモーフィズム」(多態性) という概念が存在します。
定義についての説明は様々ありますが、システム上の動作としては 「同じメソッド名でも、オブジェクトごとに異なる動作を定義できる」 性質や、「共通のインターフェースを持っていれば、異なるオブジェクトでも同じように扱うことができる」 性質のことを指します。
オーバーライドは、このポリモーフィズムの概念に基づく機能の内の1つで、既存クラスのメンバ変数や他のメソッドは変更することなく、上書きしたいメソッドだけを変更して使用することができます。
これにより、既存クラスの再利用を簡単に行うことができます。
また、先ほども説明したように、オーバーライドによって行われた処理の変更は、親クラスや他の子クラスのメソッドに影響を与えることはありません。
一方で、親クラスの処理内容を変更したい場合に、同一のメソッドを使用している子クラス側に変更を加える必要はなく、親クラス側のコードを修正するだけで済むため、保守が行いやすくなります。
オーバーロードとオーバーライドの違いは?
Javaで似たような用語に 「オーバーロード」 というものがあります。
どちらもメソッドの扱いに関する用語であり、間違われることも多いため、それぞれの違いについて説明しておきます。
Javaでは、引数の型や数などが完全に一致しない場合に、同一の名前を使用して異なるメソッドを定義することができます。
この仕様を利用して、同一クラス内に複数の同名メソッドを定義することを、オーバーロードと呼びます。
オーバーロードもまたポリモーフィズムの概念に基づく機能の内の1つであり、同一のメソッド名を使用して処理内容を使い分ける点は同じですが、使い分けをクラスの違いによって行うか、引数の差によって行うかの違いがあります。
オーバーロードになる条件は、以下の3点のうちのどれかを満たしていることです。
- 引数の型が異なる
- 引数の数が異なる
- 引数の型と数が同じでも、順番が異なる
慣れない内はややこしく感じるかと思いますが、混同しないよう注意しておきましょう。
オーバーライドの使い方
ここからは、オーバーライドの使い方について解説していきます。
基本的な使い方
オーバーライドの基本的な使い方を、サンプルコードを使って見ていきましょう。
以下のコードでは、親クラス 「Human」 と 子クラス 「Student」 を作成し、それぞれのインスタンスを生成してメソッドを実行しています。
【サンプルコード】
public class Main {
public static void main(String[] args) {
Human tanaka = new Human();
Student sato = new Student();
tanaka.setData("田中", 20);
sato.setData("佐藤", 16);
}
}
// 親クラス
class Human {
public String name;
public int age;
public void setData(String name, int age){
name = name;
age = age;
System.out.println(name + "さんは" + age + "歳です。");
}
}
//子クラス
class Student extends Human{
@Override
public void setData(String name, int age){
name = name;
age = age;
System.out.println(name + "さんは" + age + "歳の学生です。");
}
}
【実行結果】
田中さんは20歳です。
佐藤さんは16歳の学生です。
同じメソッド名でも、生成したインスタンスごとに結果が違っているのが分かりますね。
このように、メソッド名と引数の型・数・順番を全て同じにすることで、メソッドをオーバーライドすることができます。
また、オーバーライドを行う際には、メソッドの上部に 「@Override」 を記述します。
こちらはアノテーションと呼ばれるもので、厳密には必ず記述しなければいけないものではないのですが、コードの保守性を高める上ではとても重要なコードとなっています。
そのため、オーバーライドの際には合わせて記述しておくことをオススメします。
アノテーションの詳しい説明については、後ほど行います。
“super”の使い方
オーバーライドした子クラス内で親クラス側の同名メソッドを使用したい場合は、「super」を使用します。
親クラスは別名スーパークラスとも呼ばれますが、superはまさしくこのスーパークラスのことを指しています。
(ちなみに、子クラスはサブクラスとも言います)
子クラス側で同名のメソッドを使用する場合、メソッド名のみを記述すると暗黙的に子クラス側のメソッドを指定したことになるため、親クラス側のメソッドを使用したい場合は superを使って指定するメソッドを明示する必要があります。
以下のサンプルコードで実際の動きを確認してみましょう。
【サンプルコード】
public class Main {
public static void main(String[] args) {
Student sato = new Student();
sato.setData("佐藤", 16);
}
}
// 親クラス
class Human {
public String name;
public int age;
public void setData(String name, int age){
name = name;
age = age;
System.out.println(name + "さんは" + age + "歳です。");
}
}
//サブクラス
class Student extends Human{
@Override
public void setData(String name, int age){
super.setData(name, age);
System.out.println(name + "さんは学生です。");
}
}
【実行結果】
佐藤さんは16歳です。
佐藤さんは学生です。
上記のコードで生成したインスタンスは Studentクラスのみですが、メソッドの実行により親クラスと子クラス両方の処理内容が表示されているのが分かると思います。
このように、superを使用することで親クラス側のメソッドを実行することが可能です。
オーバーライドを使用するうえでの決まりごと
便利な機能であるオーバーライドですが、使用する上で守らなければならない決まりごとや、注意すべき点がいくつかあります。
順に見ていきましょう。
メソッドの戻り値の型と引数
前述の通り、メソッドをオーバーライドする際には、クラス名と引数の型・数・順番が全て同じである必要があります。
どれか1つでも異なってしまうとオーバーライドとはみなされないため、注意が必要です。
@Overrideアノテーションについて
@Overrideアノテーションは、記述するメソッドがオーバーライドしたものであることを明示するための機能です。
アノテーションを使用する最大のメリットは、コードの記述ミスを事前に防げる点にあります。
アノテーションを記述すると、親クラス側のメソッドと異なる名前や引数を記述した場合に、コンパイラがエラーメッセージを表示するようになります。
アノテーションがない場合、メソッドの記述内容にミスがあってもエラーが発生することはなく、別のメソッドとしてコンパイルが通ってしまうため、結果としてプログラムが意図しない動作をする原因となってしまいます。
ミスを事前に防ぐためにも、オーバーライドする際には必ず記述するようにしておきましょう。
static修飾子について
オーバーライドが可能なのはインスタンスメソッドのみであり、クラスメソッドはオーバーライドすることができません。
そのため、クラスメソッドであることを示す static 装飾子の付いたメソッドはオーバーライドできないので、注意が必要です。
private修飾子について
「private」を含むアクセス装飾子の違いは、オーバーライドをする上でも重要なポイントです。
前述の通り、オーバーライドをする際の条件の1つとして、アクセスレベルは親クラスと同じかそれよりも緩い制限である必要があります。
private装飾子はアクセス装飾子の中でも最も制限が厳しいため、特に注意が必要です。
abstract修飾子について
オーバーライドを必ず行わなければいけないケースとして、抽象クラス (abstractクラス) を継承した場合が挙げられます。
抽象クラスは、継承して利用されることを前提としたクラスであり、クラス内に1つ以上含まれる抽象メソッド (abstractメソッド) には処理内容の記述がなく、中身がない状態です。
そのままではクラスをインスタンス化することはできないため、抽象クラスを継承した際には、抽象メソッドをオーバーライドして処理内容を確定させる必要があります。
final修飾子について
親クラス側のメソッドに final修飾子が付いている場合は、子クラス側でそのメソッドをオーバーライドすることはできません。
final装飾子は、既に定義されているクラスやメソッドなどの状態を変更することを禁止する装飾子です。
クラスに付けられている場合は継承不可、メソッドの場合はオーバーライド不可、変数につけた場合は再代入を不可とします。
子クラス側でオーバーライドされたくないメソッドがある場合には、final装飾子を使用するといいでしょう。
throwsで例外を投げる場合の例外クラスの指定
オーバーライドするメソッドが親クラス側で throwsを使って例外を投げるよう記述されている場合、
サブクラス側のメソッドが throwする例外は親クラスのメソッドと同じ例外クラスか、その例外クラスのサブクラスである必要があります。
ただし、親クラスのメソッドに throwsがあっても、サブクラス側で throwsを記述しないことは可能です。
まとめ
今回は、オーバーライドの使い方について解説をしてきました。
慣れない内は使いづらさを感じるかもしれませんが、実際の開発現場でも活用される便利な機能ですので、この機会にぜひ覚えてみてくださいね!
Javaの勉強方法は?
書籍やインターネットで学習する方法があります。昨今では、YouTubeなどの動画サイトやエンジニアのコミュニティサイトなども充実していて多くの情報が手に入ります。
そして、より効率的に知識・スキルを習得するには、知識をつけながら実際に手を動かしてみるなど、インプットとアウトプットを繰り返していくことが重要です。特に独学の場合は、有識者に質問ができたりフィードバックをもらえるような環境があると、理解度が深まるでしょう。
ただ、Javaに限らず、ITスキルを身につける際、どうしても課題にぶつかってしまうことはありますよね。特に独学だと、わからない部分をプロに質問できる機会を確保しにくく、モチベーションが続きにくいという側面があります。独学でモチベーションを維持する自信がない人にはプログラミングスクールという手もあります。費用は掛かりますが、その分スキルを身につけやすいです。しっかりと知識・スキルを習得して実践に活かしたいという人はプログラミングスクールがおすすめです。
プログラミングスクールならテックマニアがおすすめ!

ITスキル需要の高まりとともにプログラミングスクールも増えました。しかし、どのスクールに通うべきか迷ってしまう人もいるでしょう。そんな方にはテックマニアをおすすめします!これまで多くのITエンジニアを育成・輩出してきたテックマニアでもプログラミングスクールを開講しています。
<テックマニアの特徴>
・たしかな育成実績と親身な教育 ~セカンドキャリアを全力支援~
・講師が現役エンジニア ~“本当”の開発ノウハウを直に学べる~
・専属講師が学習を徹底サポート ~「わからない」を徹底解決~
・実務ベースでスキルを習得 ~実践的な凝縮カリキュラム~
このような特徴を持つテックマニアはITエンジニアのスタートラインとして最適です。
話を聞きたい・詳しく知りたいという方はこちらからお気軽にお問い合わせください。