Kodrill

継承とインタフェースの使用

Java SE 17 Silver (1Z0-825-JPN) 試験

スーパークラスとサブクラス/抽象クラス/オーバーライド/キャストとポリモーフィズム/final クラス/インタフェース/デフォルト・プライベートメソッド/シール・クラス

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

ログインなしで試す

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

5 問を試す

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

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

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

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

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

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

継承とインタフェースの使用の要点

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

この分野は Silver で最も出題項目が多く、継承の細かいルールと、Java SE 8 以降に拡張されたインタフェース (デフォルト・メソッド、static メソッド、プライベート・メソッド)、Java SE 17 で正式に入ったシール・クラスが問われます。

「オーバーライドされるのはインスタンスメソッドだけ」「どのメソッドを呼ぶかの決まり方は、オーバーロードはコンパイル時、オーバーライドは実行時」という 2 つの原則を押さえると、紛らわしい問題も整理できます。

コンストラクタの連鎖

コンストラクタの最初の文は、this(...) (同じクラスの別のコンストラクタ) か super(...) (親クラスのコンストラクタ) のどちらかです。どちらも書かなければ super(); が自動で入ります。そのため new すると、親クラスのコンストラクタの本体から順に実行されます。

Main.java
class Base {    Base(int level) {        System.out.println("Base(" + level + ")");    }}​class Derived extends Base {    Derived() {        this(1);        System.out.println("Derived()");    }​    Derived(int level) {        super(level * 10);        System.out.println("Derived(int)");    }}​public class Main {    public static void main(String[] args) {        new Derived();    }}
ターミナル
java Main
Base(10)
Derived(int)
Derived()

コンストラクタを 1 つも書かないサブクラスには Sub() { super(); } というデフォルトコンストラクタが追加されます。親クラスに引数なしのコンストラクタがなければ、このときコンパイルエラーになります。

オーバーライドされるもの・されないもの

オーバーライドされるのはインスタンスメソッドだけです。フィールドと static メソッドはオーバーライドされず、サブクラスの同名のものは親のものを隠すだけです。隠されたフィールドや static メソッドのどちらが使われるかは、変数の型で決まります。

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

オーバーライドするメソッドには、次の制限があります。

・アクセス修飾子は、元と同じかより広く (protected → public は可、逆は不可) ・戻り値の型は、元と同じかそのサブクラス (共変戻り値。プリミティブ型は同じ型のみ) ・throws に書けるチェック例外は、元と同じかそのサブクラスだけ (減らしたり、なくしたりするのは可) ・final メソッドはオーバーライドできない ・インスタンスメソッドを static メソッドで隠す (またはその逆) ことはできない

Main.java
import java.io.IOException;​class Loader {    void load() throws IOException {    }}​class FileLoader extends Loader {    @Override    void load() throws Exception {    }}​public class Main {    public static void main(String[] args) {        System.out.println("ok");    }}
ターミナル
javac Main.java

コンパイルエラー (10 行目): 元のメソッドの IOException より広い Exception を throws に書いている

キャストと、呼ばれるメソッドの決まり方

クラス型どうしのキャストは、継承関係にある場合だけ書けます。継承関係のないクラスへのキャストはコンパイルエラーです。一方、final でないクラスからインタフェースへのキャストは、そのクラス自身がインタフェースを実装していなくてもコンパイルは通ります (サブクラスが実装しているかもしれないため)。実体が実装していなければ、実行時に ClassCastException になります。

Main.java
interface Flyer {}​class Bird {}​public class Main {    public static void main(String[] args) {        Bird b = new Bird();        System.out.println("キャスト前");        Flyer f = (Flyer) b;        System.out.println("キャスト後");    }}
ターミナル
java Main
キャスト前

実行時に例外が発生: ClassCastException

オーバーライドされたメソッドは、実行時のオブジェクトのクラスのものが呼ばれます。一方、オーバーロードのどれを呼ぶかは、コンパイル時に、引数の変数の型で決まります。実体が String でも、Object 型の変数を渡せば Object 版が呼ばれます。

Main.java
class Printer {    void print(Object o) {        System.out.println("Object");    }​    void print(String s) {        System.out.println("String");    }}​public class Main {    public static void main(String[] args) {        Printer p = new Printer();        Object o = "text";        p.print(o);        p.print("text");    }}
ターミナル
java Main
Object
String

抽象クラスと final クラス

抽象クラスは new できませんが、コンストラクタを持てます (サブクラスの super(...) から呼ばれます)。また、インタフェースを実装した抽象クラスは、インタフェースのメソッドの一部を実装しないままにできます。残りは具象サブクラスで実装します。

final を付けたクラスは継承できず、final を付けたメソッドはオーバーライドできません。String・Integer などの多くの標準クラスは final です。abstract と final は意味が矛盾するので、同時には付けられません。

インタフェースのメソッド

インタフェースには、抽象メソッドのほかに次のメソッドを書けます。

・デフォルト・メソッド (Java SE 8): default を付けた、処理を持つメソッド。実装クラスに引き継がれ、オーバーライドもできる ・static メソッド (Java SE 8): 実装クラスには引き継がれない。インタフェース名.メソッド名() でしか呼べない ・プライベート・メソッド (Java SE 9): インタフェースの中のデフォルト・メソッドなどから共通処理として呼ぶためのメソッド

Main.java
interface Calculator {    static int twice(int n) {        return n * 2;    }​    default int addTax(int price) {        return round(price * 1.1);    }​    private int round(double value) {        return (int) Math.round(value);    }}​class Shop implements Calculator {}​public class Main {    public static void main(String[] args) {        System.out.println(Calculator.twice(21));        System.out.println(new Shop().addTax(1000));    }}
ターミナル
java Main
42
1100

Shop.twice(21) や new Shop().twice(21) と書くと、static メソッドは引き継がれていないのでコンパイルエラーです。

同じシグネチャのデフォルト・メソッドを持つ 2 つのインタフェースを実装すると、どちらを使うか決まらないので、クラスでオーバーライドしなければコンパイルエラーです。オーバーライドの中では インタフェース名.super.メソッド名() で、それぞれのデフォルト・メソッドを呼べます。また、親クラスから継承したメソッドとデフォルト・メソッドが衝突した場合は、親クラスのメソッドが優先されます。

Main.java
interface Walker {    default String move() {        return "歩く";    }}​interface Swimmer {    default String move() {        return "泳ぐ";    }}​class Duck implements Walker, Swimmer {    @Override    public String move() {        return Walker.super.move() + "と" + Swimmer.super.move();    }}​class Animal {    public String move() {        return "Animal の move";    }}​class Frog extends Animal implements Walker {}​public class Main {    public static void main(String[] args) {        System.out.println(new Duck().move());        System.out.println(new Frog().move());    }}
ターミナル
java Main
歩くと泳ぐ
Animal の move

シール・クラス

Java SE 17 からのシール・クラス (sealed) は、継承・実装できる型を permits に書いたものだけに限定する仕組みです。permits に書かれていないクラスが継承しようとすると、コンパイルエラーになります。

Main.java
sealed interface Shape permits Circle {}​final class Circle implements Shape {}​final class Square implements Shape {}​public class Main {    public static void main(String[] args) {        System.out.println("ok");    }}
ターミナル
javac Main.java

コンパイルエラー (7 行目): Square は Shape の permits に含まれていない

permits に書いたサブクラスには、次のどれかを必ず付けます。付け忘れるとコンパイルエラーです。

・final: これ以上継承させない ・sealed: さらに継承先を permits で限定する ・non-sealed: 制限を解除し、どのクラスでも継承できるようにする

サブクラスがすべて同じソースファイルにある場合は、permits を省略できます (そのファイルのサブクラスが許可されたものになります)。

Main.java
sealed abstract class Ticket {    abstract int price();}​final class Adult extends Ticket {    int price() {        return 1800;    }}​non-sealed class Child extends Ticket {    int price() {        return 1000;    }}​class Infant extends Child {    @Override    int price() {        return 0;    }}​public class Main {    public static void main(String[] args) {        Ticket[] tickets = {new Adult(), new Child(), new Infant()};        int total = 0;        for (Ticket t : tickets) {            total += t.price();        }        System.out.println(total);    }}
ターミナル
java Main
2800

Child は non-sealed なので、permits に関係なく Infant が継承できます。

試験でよくある引っかけ

  • フィールドと static メソッドは隠すだけ

    親の型の変数からは、親のフィールド・static メソッドが使われます。オーバーライドされるのはインスタンスメソッドだけです。

  • オーバーライドの throws

    元のメソッドより広いチェック例外を throws に書くとコンパイルエラーです。減らすのは問題ありません。

  • インタフェースへのキャスト

    final でないクラスからインタフェースへのキャストはコンパイルが通り、実体が実装していなければ実行時に ClassCastException です。

  • オーバーロードは変数の型で決まる

    Object o = "text"; p.print(o); は print(Object) が呼ばれます。オーバーロードはコンパイル時に決まります。

  • インタフェースの static メソッド

    実装クラスには引き継がれません。インタフェース名.メソッド名() で呼びます。

  • permits のサブクラスの修飾子

    シール・クラスの許可されたサブクラスには、final・sealed・non-sealed のどれかが必要です。

問題で確認する

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

出典・参考

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