Kodrill

継承とポリモフィズム

Java SE Bronze (1Z0-818-JPN) 試験

サブクラスの定義と使用/メソッドのオーバーライド/抽象クラスやインタフェースの定義と実装/ポリモフィズムを使用するコードの作成/参照型の型変換/パッケージ宣言とインポート

問題数
20 問
合格ライン
60%
実行して確認済み
13 問
この分野の要点を読む6 章・約 14 分。実行して確かめたコード例と、試験でよくある引っかけをまとめています

ログインなしで試す

無料の 5 問を、1問ごとに正誤と解説を見ながら解けます。解答は保存されません。

5 問を試す

無料登録して学習を記録する

学習履歴・ダッシュボード・ブックマーク・模試モードが使えます。

★ 残り 15 問はプレミアム会員限定です

無料プランでは先頭 5 問まで解けます。プレミアムなら全問題・苦手問題の復習・広告非表示が使えます。
料金プランを見る

問題と解説を見る (無料)

登録しなくても、次の5問は問題文と解説をそのまま読めます。

継承とポリモフィズムの要点

内容の確認日: 2026-10-03

この分野は Bronze の中でも出題数が多く、「どのクラスのメソッドが実行されるか」「そもそもコンパイルできるか」を見分ける問題が中心です。出題項目は「サブクラスの定義と使用」「メソッドのオーバーライド」「抽象クラスやインタフェースの定義と実装」「ポリモフィズムを使用するコードの作成」「参照型の型変換」「パッケージ宣言とインポート」の 6 つです。

迷ったときは、「呼び出せるかどうかは変数の型で決まり、実際に動くのはオブジェクトのクラスのメソッド」という原則に立ち返ると整理できます。

サブクラスの定義とコンストラクタ

class Car extends Vehicle のように extends で親クラスを指定すると、親クラスのフィールドとメソッドを引き継いだサブクラスになります。Java のクラスが継承できるのは1 つのクラスだけです (extends A, B はコンパイルエラー)。extends を書かないクラスは、自動的に java.lang.Object を継承します。

サブクラスのコンストラクタの先頭には、書かなくても super(); (親クラスの引数なしコンストラクタの呼び出し) が自動で入ります。そのため、オブジェクトを作ると親クラスのコンストラクタが先に実行されます。

Main.java
class Vehicle {    Vehicle() {        System.out.println("Vehicle");    }}​class Car extends Vehicle {    Car() {        System.out.println("Car");    }}​public class Main {    public static void main(String[] args) {        new Car();    }}
ターミナル
java Main
Vehicle
Car

親クラスに引数なしのコンストラクタがない場合 (引数ありのコンストラクタだけを定義した場合) は、自動で入る super(); が呼び出し先を見つけられず、コンパイルエラーになります。サブクラスのコンストラクタの先頭で super("名前") のように、引数を渡して明示的に呼び出す必要があります。

Main.java
class Parent {    Parent(String name) {        System.out.println(name);    }}​class Child extends Parent {    Child() {        System.out.println("Child");    }}​public class Main {    public static void main(String[] args) {        new Child();    }}
ターミナル
javac Main.java

コンパイルエラー (8 行目): Parent に引数なしのコンストラクタがないため、暗黙の super() を呼び出せない

super(...) も this(...) と同じく、コンストラクタの最初の文に書かなければなりません。

メソッドのオーバーライド

親クラスのメソッドと同じ名前・同じ引数 (型・数・順番) のメソッドをサブクラスで定義すると、親のメソッドを上書きするオーバーライドになります。戻り値の型も基本的に同じにします (int を long に変えるなどはコンパイルエラー)。メソッドの前に @Override を付けると、正しくオーバーライドできていない場合にコンパイラがエラーで知らせてくれます。

サブクラスのメソッドの中で super.メソッド名() と書くと、オーバーライドする前の親クラスのメソッドを呼び出せます。

Main.java
class Animal {    void speak() {        System.out.println("...");    }}​class Dog extends Animal {    @Override    void speak() {        System.out.println("ワン");        super.speak();    }}​public class Main {    public static void main(String[] args) {        Animal a = new Dog();        a.speak();    }}
ターミナル
java Main
ワン
...

オーバーライドするメソッドのアクセス修飾子は、元のメソッドと同じか、より広くしなければなりません。public のメソッドを修飾子なし (パッケージ内だけに公開) でオーバーライドすると、範囲が狭くなるのでコンパイルエラーです。

Main.java
class Parent {    public void show() {        System.out.println("Parent");    }}​class Child extends Parent {    void show() {        System.out.println("Child");    }}​public class Main {    public static void main(String[] args) {        new Child().show();    }}
ターミナル
javac Main.java

コンパイルエラー (8 行目): public の show() を、それより狭いアクセス範囲でオーバーライドしている

引数が違う同名のメソッドは、オーバーライドではなくオーバーロード (別のメソッドの追加) になります。また、親クラスの private メソッドはサブクラスに引き継がれないので、同じ名前のメソッドを書いてもオーバーライドにはなりません。

ポリモーフィズムと「変数の型」

親クラスの型の変数には、サブクラスのオブジェクトを代入できます (Animal a = new Dog();)。このとき、

・呼び出せるメソッドは、変数の型 (Animal) に定義されているものだけ ・実際に実行される処理は、オブジェクトのクラス (Dog) でオーバーライドされたもの

となります。サブクラスにだけあるメソッドは、親クラスの型の変数からは呼び出せません。実体がそのクラスのオブジェクトでも、コンパイルエラーです。

Main.java
class Parent {    void hello() {        System.out.println("hello");    }}​class Child extends Parent {    void bye() {        System.out.println("bye");    }}​public class Main {    public static void main(String[] args) {        Parent p = new Child();        p.hello();        p.bye();    }}
ターミナル
javac Main.java

コンパイルエラー (17 行目): 変数 p の型 Parent には bye() が定義されていない

抽象クラスを使うと、共通の処理は親クラスに書き、違う部分だけをサブクラスに実装させられます。親クラスのメソッドの中から呼んだ抽象メソッドも、実行時のオブジェクトのクラスの実装が使われます。

Main.java
abstract class Employee {    String name;​    Employee(String name) {        this.name = name;    }​    abstract int salary();​    void print() {        System.out.println(name + ": " + salary());    }}​class Engineer extends Employee {    Engineer(String name) {        super(name);    }​    int salary() {        return 300;    }}​class Manager extends Employee {    Manager(String name) {        super(name);    }​    int salary() {        return 450;    }}​public class Main {    public static void main(String[] args) {        Employee[] staff = {new Engineer("佐藤"), new Manager("鈴木")};        int total = 0;        for (Employee e : staff) {            e.print();            total += e.salary();        }        System.out.println("合計: " + total);    }}
ターミナル
java Main
佐藤: 300
鈴木: 450
合計: 750

参照型の型変換 (キャスト) と instanceof

サブクラスの型から親クラスの型への変換 (アップキャスト) は、キャストを書かなくても自動で行われます。逆に、親クラスの型からサブクラスの型への変換 (ダウンキャスト) は、(Dog) a のようにキャストを明示する必要があります。

ダウンキャストは、実体が本当にそのクラスのオブジェクトなら成功します。実体が違うクラス (例えば Cat) だった場合、コンパイルは通りますが、実行時に例外 (ClassCastException) が発生します。キャストの前に instanceof で確かめると安全です。

Main.java
class Animal {}​class Dog extends Animal {    void bark() {        System.out.println("ワン");    }}​class Cat extends Animal {}​public class Main {    public static void main(String[] args) {        Animal[] animals = {new Dog(), new Cat()};        for (Animal a : animals) {            if (a instanceof Dog) {                Dog d = (Dog) a;                d.bark();            } else {                System.out.println("Dog ではない");            }        }        Dog d = (Dog) animals[1];    }}
ターミナル
java Main
ワン
Dog ではない

実行時に例外が発生: ClassCastException

最後の行の (Dog) animals[1] は、実体が Cat なので実行時に例外になります。一方、Dog と String のように継承関係がまったくない型どうしのキャストは、成功する可能性がないのでコンパイルエラーになります。

パッケージ宣言とインポート

ソースファイルの中の順番は、package 宣言 → import 文 → クラスの宣言と決まっています。package 宣言はファイルの先頭 (コメントは除く) に 1 つだけ書けます。

Cart.java
package com.example.shop;​import java.util.ArrayList;import java.util.List;​public class Cart {    private List<String> items = new ArrayList<>();}

次のクラスは、import を書かなくても使えます。

・java.lang パッケージのクラス (String・Math・System・Integer など) ・同じパッケージのクラス

import java.util.*; のように * を使うと、そのパッケージ直下のクラスをまとめてインポートできます。ただし、サブパッケージのクラスは含まれません (java.util.* で java.util.function のクラスは使えない)。import を書かずに java.util.List のように完全修飾名で書くこともできます。

試験でよくある引っかけ

  • 暗黙の super() と親のコンストラクタ

    親クラスに引数なしのコンストラクタがないと、サブクラスのコンストラクタで super(...) を明示しない限りコンパイルエラーです。

  • オーバーライドでアクセスを狭める

    public のメソッドを、修飾子なしや private でオーバーライドするとコンパイルエラーです。

  • 親の型の変数からサブクラスのメソッド

    Parent p = new Child(); の p からは、Child にしかないメソッドを呼べません (コンパイルエラー)。

  • ダウンキャストの失敗

    実体が違うクラスのダウンキャストは、コンパイルは通り、実行時に ClassCastException になります。

  • 引数が違う同名メソッド

    引数の型や数が違うと、オーバーライドではなくオーバーロードです。親の型の変数からは呼べません。

  • package と import の順番

    package 宣言 → import 文 → クラスの順です。import を package より前に書くとコンパイルエラーです。

問題で確認する

この分野の問題を、解説つきで読めます (登録不要)。

出典・参考

コード例は、試験の対象バージョンで実際にコンパイル・実行して結果を確認しています。