【Java復習3日目】サンプルコードから学び直すJava入門③

# サンプルコード(クラス初期化子とインスタンス初期化子)

```java
import java.util.Random;

class StaticInitializer {
    // 静的フィールド(=クラス変数)
    // -> クラスで共通して利用する変数
    // => インスタンス間で共有
    private static int staticCounter;
    private static int instanceCounter = 0;

    // 動的フィールド(インスタンス変数)
    // -> インスタンス毎に利用する変数
    // => インスタンス毎に異なる
    private int staticId;
    private int instanceId;

    // クラス初期化子(=静的初期化子)
    // -> クラスの初期化時に呼び出される処理
    static {
        Random rand = new Random();
        staticCounter = rand.nextInt(10)* 100;
    }

    // インスタンス初期化子
    // インスタンス生成時(=コンストラクタの呼び出し前)に呼び出される処理
    {
        instanceId = ++instanceCounter;
    }

    // コンストラクタ
    // -> インスタンス初期化子の実行後に呼び出される
    public StaticInitializer() {
        staticId = ++staticCounter;
    }

    public int getStaticId() {
        return staticId;
    }

    public int getInstanceId() {
        return instanceId;
    }
}

class Main {
    public static void main(String[] args) {
        StaticInitializer a = new StaticInitializer();
        StaticInitializer b = new StaticInitializer();
        StaticInitializer c = new StaticInitializer();

        System.out.println("StaticId a: " + a.getStaticId() + ", InstanceId a: " + a.getInstanceId());
        System.out.println("StaticId b: " + b.getStaticId() + ", InstanceId b: " + b.getInstanceId());
        System.out.println("StaticId c: " + c.getStaticId() + ", InstanceId c: " + c.getInstanceId());
    }
}
```

## クラス初期化子とインスタンス初期化子
`static {...}`で宣言する`クラス初期化子`は、**クラスの初期化時**に呼び出される処理。
`{...}`で宣言する`インスタンス初期化子`は、**インスタンスの初期化時**(=`コンストラクタ`の**実行直前**)に呼び出される処理。

なお、`クラス`が`初期化`されるタイミングは以下の通り。

> - `インスタンス`の**生成**時
> - `クラスメソッド`の**呼び出し**時
> - `クラス変数`への値の**代入**時<br>→`クラス変数`を利用する場合は"<クラス名>.<クラス変数>"で呼び出すため
> - `定数`でない`クラス変数`の値の**取得**時<br>→`変数`であることから、`初期化`して値を**厳密に定義する必要がある**ため<br>⇒`定数`は値が**既に**厳密に定義されているため、取得時に`初期化`は行われない。

また、`インスタンス`が`初期化`されるタイミングは以下の通り。

> - `コンストラクタ`が呼び出される**直前**

### クラス初期化子の利用場面
何らかの計算が必要な`クラス変数`を`初期化`する場合、`クラス初期化子`を用いて初期化処理を記述する。

### インスタンス初期化子の利用場面
`コンストラクタ`を`多重定義`(=`オーバーロード`)する場合、それらの**共通部分**は`インスタンス初期化子`を用いて初期化処理を記述する。

***

# パッケージ

`パッケージ宣言(package declaration)`によって、定義した`クラス`や`インタフェース`を特定の`パッケージ`に所属させることができる。
なお、`パッケージ宣言`は**2つ**以上置くことはできず、`パッケージ名`の先頭文字は**小文字**にする。
ここで、`パッケージ宣言`がない場合、その`ソースファイル`中で定義した`クラス`は`無名パッケージ(unnamed package)`に属する。

また、基本的に`パッケージ名`と同名である`ディレクトリ`の中に`パッケージ宣言`を行う`ソースファイル`を置く。
この場合、`コンパイル`時に、`ディレクトリ`内に置かれた`ソースファイル`で定義した`クラスファイル`(=`.class`)が`ディレクトリ`内に格納される。

```java:a/A1.java
// パッケージと同名のディレクトリ中にソースファイルを置く
package a;

// 異なるディレクトリに置かれたソースファイルからでも、"import a.A1[A2]"のインポート宣言によって単純名で利用可能
public class A1 { ... }
class A2 { ... }
```

## 一意なパッケージ名の命名
**一意**な`パッケージ名`を与える場合、`インターネットアドレス`を**逆順**に並べた`パッケージ名`で命名する。

## クラスファイルの検索
`インポート宣言`によって`インポート`される`クラスファイル`は、以下の3箇所から検索される。

> 1. `ブートストラップクラスパス` … `Javaプラットフォーム`を構成するクラス。
> 2. `インストール型拡張機能` … `Java拡張機能機構`を構成するクラス。
> 3. `ユーザクラスパス` … `拡張機能機構`を利用しないユーザ定義クラス。`-classpath`オプションを用いて実行する。

`ユーザクラスパス`は、以下のように実行する。

```bash:ユーザクラスパスを指定して実行
% java -classpath <検索ディレクトリ1>;<検索ディレクトリ2>;... <実行クラス名>
```

# パッケージの役割
`パッケージ`の主な役割は、以下の3つ。

|役割|内容|
|:--|:--|
|名前の衝突回避|`同名クラス`を`完全限定名`の利用によって区別可能にする。|
|カテゴリによる分類|機能が似ている`クラス`をカテゴライズする。|
|カプセル化(アクセス制御)|無関係`クラス`からの`アクセス`を制御できる。|

## クラスを利用可能にする型インポート宣言(type import declaration)
異なる`パッケージ`に属する`クラス`を、`完全限定名(fully qualified name)`ではなく
`単純名(simple name)`で利用できるようにする`インポート宣言`の種類は、以下の2つ。

|宣言|形式|
|:--|:--|
|単一型インポート宣言(single-type-import declaration)|`import <完全限定名>;`|
|オンデマンド型インポート宣言(type-import-on-demand declaration)|`import <パッケージ名>.*;`|

ただし、`オンデマンド型インポート宣言`を用いて`インポート`した`パッケージ`同士に
`同名クラス`が存在する場合は`コンパイルエラー`が生じるため、
利用クラスが限定される場合は`単一型インポート宣言`を用いる。

```java:同名クラスの例
import java.util.*;
import java.sql.*;

Date a = new Date();  // Dateはutilパッケージにもsqlパッケージにも存在するため、コンパイルエラーが発生
```

## クラスの静的メンバを利用可能にする静的インポート宣言(static import declaration)
異なる`パッケージ`に属する`クラス`の`メンバ`を利用する場合は、`静的インポート宣言`を用いる。

`静的インポート宣言`も`型インポート宣言`と同様、以下の2種類が存在する。

|宣言|形式|
|:--|:--|
|単一静的インポート宣言(single-static-import declaration)|`import static <完全限定名>.<メンバ変数の識別子>;`|
|オンデマンド静的インポート宣言(static-import-on-demand declaration)|`import static <完全限定名>.*;`|

***

# サンプルコード(派生とコンストラクタ, ポリモーフィズム, 拡大変換と縮小変換)

```java:SuperConstructor.java
// スーパークラス
class A {
    // "private"や"final"キーワードを用いたフィールドは継承されない
    private int x;
    private int y;

    // コンストラクタ
    A(int x, int y) {
        this.x = x;
        this.y = y;
    }

    void setX(int x) { this.x = x; }
    void setY(int y) { this.y = y; }

    int getX() { return x; }
    int getY() { return y; }
}

// サブクラス
class B extends A{
    private int z;

    // コンストラクタ
    // スーパークラスのコンストラクタはsuper(...)で呼び出す
    // -> スーパークラスのコンストラクタを呼び出さない場合、引数を取らないコンストラクタsuper()が自動的に呼び出される
    // => スーパークラスのコンストラクタを呼び出さない場合、
    //    スーパークラスで引数を取らないコンストラクタを定義していない場合はコンパイルエラーが発生
    B(int x, int y, int z) {
        super(x, y);
        this.z = z;
    }

    void setZ(int z) { this.z = z; }
    int getZ() { return z; }
}

class Main {
    public static void main(String[] args) {
        // スーパークラスのオブジェクト
        A a = new A(10, 20);
        // サブクラスのオブジェクト
        B b = new B(30, 40, 50);

        // スーパークラスのクラス型変数は、サブクラスのオブジェクトを参照できる
        // -> 暗黙的に"A a1 = (A) b"の拡大変換が実行される
        // => ポリモーフィズム
        A a1 = b;
        System.out.println( "x of Sub: " + a1.getX() );
        System.out.println( "y of Sub: " + a1.getY() );

        // サブクラスのクラス型変数は、スーパークラスのオブジェクトを参照できない
        // -> 暗黙的には"B b1 = (B) a"の縮小変換は実行されない
        B b1 = a;     // コンパイルエラー
                    // -> スーパークラスのオブジェクトは、サブクラスで追加されたフィールドを持たないため
        System.out.println("z of Main: " + b1.getZ();)  // コンパイルエラー
    }
}
```

# 派生とコンストラクタ, ポリモーフィズム

`スーパークラス`を`派生(derive)`した`サブクラス`では、`スーパークラス`の`コンストラクタ`は**直接的には継承されない**。
ただし、`super(...)`によって`スーパークラス`の`コンストラクタ`を呼び出すことができる。

また、`サブクラス`で`スーパークラス`の`コンストラクタ`を明示的に呼び出さない場合、
`サブクラス`の`デフォルトコンストラクタ`を含む`コンストラクタ`の先頭で、
`スーパークラス`の`デフォルトコンストラクタ`である`super()`が**自動的に呼び出される**。

さらに、`Object`クラスは**すべてのクラスの**`上位クラス`であるため、以下の2つのことが言える。
> 1. `extends`を付与せずに定義されたクラスは、すべて`Object`クラスの`サブクラス`となる。
> 2. `Object`型をとる仮引数には、すべてのクラス型の実引数をとることができる。(=`ポリモーフィズム`)

※`Java`では`多重継承`はサポートされない。

また、`final`や`private`キーワードを付与した`クラス`・`メソッド`も`サブクラス`に**継承されない**。
なお、`finalクラス`内のすべての`メソッド`は自動的に`final`メソッドとなる。

# is-A関係をもつクラスオブジェクトの参照可能範囲

`スーパークラス`の`クラス型変数`は、`サブクラス`の`オブジェクト`を参照することができる。
→`サブクラス`の`オブジェクト`は、`スーパークラス`の`フィールド`を持っているため。
⇒`サブクラス`は一種の`スーパークラス`である

一方で、`サブクラス`の`クラス型変数`は、`スーパークラス`の`オブジェクト`を参照することはできない。
→`スーパークラス`の`オブジェクト`は、`サブクラス`の`フィールド`を持っていないため。
⇒`スーパークラス`は一種の`サブクラス`でない

# 拡大変換と縮小変換
[参考: Java復習1日目](https://qiita.com/b150005/items/15646743a3331f6670b2#%E7%94%A8%E8%AA%9E%E9%9B%86)

`参照型`の`拡大変換(widening reference conversion, アップキャスト)`は、**参照可能範囲が広い**`スーパークラス`への変換を指し、
`縮小変換(narrowing reference conversion, ダウンキャスト)`は、**参照可能範囲が狭い**`サブクラス`への変換を指す。

ただし、`参照型`における`縮小変換`は原則避ける必要がある。

***

# サンプルコード(静的結合と動的結合, instanceof演算子)

```java:Polymorphism.java
class Super {
    private String name;

    // コンストラクタ
    public Super(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void print() {
        System.out.println(getName() + ": Super");
    }
}

class Sub extends Super {

    // コンストラクタ
    public Sub(String name) {
        super(name);
    }

    // オーバーライドメソッド
    // -> @Overrideアナテイションを用いて明示的に宣言
    @Override public void print() {
        System.out.println(getName() + ": Sub");
    }
}

public class Polymorphism {
    public static void main(String[] args) {
        // サブクラスのオブジェクト
        Sub sub = new Sub("Super or Sub");

        // スーパークラスのクラス型変数にサブクラスのオブジェクトの「参照先」を渡す
        // -> ポリモーフィズム
        Super sup = sub;

        // スーパークラスのクラス型変数からサブクラスのprint()メソッドが呼び出される
        // -> メソッドを呼び出す「オブジェクト」のクラス型をもとに呼び出すメソッドが決定(=静的結合/早期結合)されるのではなく、
        //    オブジェクトの「参照先」のクラス型をもとに呼び出すメソッドが決定(=動的結合/遅延結合)
        sup.print();

        // スーパー/サブクラスのオブジェクトを格納する配列
        Super[] a = {
            new Super("Super 1"),
            new Super("Super 2"),
            new Sub("Sub 1"), 
            new Sub("Sub 2")
        };

        // 配列の構成要素毎に行う処理
        for (Super i : a) {
            // 構成要素がサブクラスである場合の処理
            // -> instanceof演算子を用いて暗黙的にダウンキャストできる下位クラスであればtrueを返却
            // => 下位クラスのメソッドを利用する場合は、明示的にダウンキャストを行う
            if (i instanceof Sub) {
                ((Sub) i).print();
            }
            // 構成要素がスーパークラスである場合の処理
            else {
                i.print();
            }
        }
    }
}
```

```java:実行結果
Super or Sub: Sub
```

# 静的結合(static binding)と動的結合(dynamic binding)

`静的結合/早期結合(early binding)`では、呼び出すメソッドが`コンパイル`時に決定され、
`動的結合/遅延結合(late binding)`では、呼び出すメソッドが`実行`時に決定される。

`Java`では、`動的結合`方式が採用される。

# オブジェクト指向の三大要素
`オブジェクト指向`における三大要素は、以下の通り。

> 1. クラス(カプセル化)
> 2. 継承(inheritance)
> 3. 多相性(polymorphism)

# instanceof演算子

```java:instanceof演算子
<クラス型変数> instanceof <クラス>
// クラス型変数が指定したクラス型に暗黙的にキャストできる下位クラスであればtrueを、
// そうでなければfalseを返却
```

***

# サンプルコード(抽象クラスの役割)

```java:Abstract.java
// 抽象クラス(スーパークラス)
// -> 関連性のある下位クラス同士をグループ化することで、多相性を活用できるようにする
abstract class Symbol {
    // (Objectクラスで定義された)非抽象メソッドを抽象メソッドとしてオーバーライド
    @Override public abstract String toString();
}

// 実装クラス(サブクラス)
class Slash extends Symbol {
    // 抽象メソッドの実装
    @Override public String toString() {
        return "/";
    }
}

// 実装クラス(サブクラス)
class Asterisk extends Symbol {
    // 抽象メソッドの実装
    @Override public String toString() {
        return "*";
    }
}

class Abstract {
    public static void main(String[] args) {
        Symbol[] a = {
            new Slash(),
            new Asterisk()
        };

        for (Symbol i : a) {
            if (i instanceof Slash) {
                System.out.println( "Slash: " + ((Slash) i).toString() );
            }
            else if (i instanceof Asterisk) {
                System.out.println( "Asterisk: " +((Asterisk) i).toString() );
            }
        }
    }
}
```

***

# サンプルコード(文書化コメント)

```java:文書化コメント
/**
 * クラスDocumentationCommentは、〜を表す。
 * @author <実装者>
 * {@code <変数名・値>}は〜を表す。
 * @return <戻り値>
 * @param <引数名> <解説>
 * @see <参照先>
 * @see <a href="<相対URLまたは絶対URL>"><ラベル></a>
 * @see <完全限定名>#<メンバ> <ラベル>
 */
public class DocumentationComment {
    ...
}
```

# 文書化コメント(documentation comment)
[参考: Javadoc ドキュメンテーションコメントの書き方](https://qiita.com/maku77/items/6410c67ce95e08d8d1bd)
`文書化コメント`は、`javadoc`というツールを用いてプログラムの**仕様書**を生成する際に利用するコメントアウト。

また、`javadoc`を起動するコマンドは以下の通り。

```bash:javadocの起動
% javadoc <オプション> <パッケージ名> <ソースファイル> @<引数ファイル>
```

***

# 抽象クラスとインタフェース
`抽象クラス`は`クラス`**に対して**`単一継承(single inheritance)`しか認められないのに対し、
`インタフェース`は`クラス`**に対して**`多重継承(multiple inheritance)`が認められる。

ただし、`インタフェース`への`多重継承`は認められない。

***

# サンプルコード(String.format()メソッド)

```java:StringFormat.java
public class StringFormat {
    public static void main(String[] args) {
        // 形式(=フォーマット)の変換
        // printf()メソッドとは異なり、String型の文字列に変換する
        String s1 = String.format("%5d", 123);
        String s2 = String.format("%9.3f", 123.45);

        System.out.println("s1: " + s1);
        System.out.println("s2: " + s2);
    }
}
```

```java:実行結果
s1:   123
s2:   123.450
```

# フォーマットを指定するString.format()メソッド
[参考: Java復習2日目(printf()メソッド)](https://qiita.com/b150005/items/15646743a3331f6670b2#%E5%AE%9A%E7%BE%A9)
`System.out.printf()`メソッドは出力先が`コンソール`であるのに対し、
`String.format()`メソッドは出力先が`String`型文字列となる。

## 定義

```java
String String.format(String format, Object... args)
// パラメータ
// format: 「出力フォーマット」を表す文字列
// args: 参照する値
```

***

# サンプルコード(コマンドライン引数)

```java:CommandLine.java
public class CommandLine {
    // main()メソッドの引数argsは、コマンドライン引数(command-line argument)を表す
    // -> "java <クラス名> <文字列1> <文字列2> ..."というように引数を指定できる。
    public static void main(String[] args) {
        for (String i : args) {
            System.out.println(i);
        }
    }
}
```

```bash:実行
% java CommandLine ABC DEF GHI
```

```java:実行結果
ABC
DEF
GHI
```

## コマンドライン引数(command-line argument)
`main(String[] args)`メソッドの`args`は`コマンドライン引数`を表す。
実行時に`コマンドライン引数`を付与した場合、`main()`メソッドが受け取る。

***

# サンプルコード(ラッパクラス)

```java:Wrapper.java
public class Wrapper {
    public static void main(String[] args) {
        // ラッパクラスを用いた定義
        // -> int型 → Integer型 へのオートボクシング(auto boxing)
        Integer i = 3;
        // 基本型を用いた定義
        int j = 7;

        System.out.println("Integer: " + i);
        System.out.println("int: " + j);
    }
}
```

# ラッパクラス(wrapper class)
`基本型`を`クラス`として提供するクラス。

`ラッパクラス`が作成された目的は、主に以下の3つ。

> 1. `基本型`の特性を`クラス変数`として提供
> <br>→ `Boolean`型を除いて、`基本型`の最大・最小値を表す`MIN_VALUE`・`MAX_VALUE`が提供
> 2. 対応する`基本型`の値をもった`クラス型オブジェクト`を生成可能にする
> 3. 2.に関連し、値に関する各種操作を`メソッド`として提供
> <br>→ `整数値`は`toString()`メソッドを持たないが、`Integer型`は`toString()`メソッドをもつ。

***

# サンプルコード1(例外処理)

```java:ExceptionHandler.java
import java.util.InputMismatchException;
import java.util.Scanner;

public class ExceptionHandler {
    public static void main(String[] args) {
        Scanner stdIn = new Scanner(System.in);

        // try節 - 例外が送出(throw)される可能性のあるブロック
        try {
            System.out.print("100 / ");
            
            // int型でない値が入力された場合はInputMismatchExceptionが発生
            // -> その場合、ストリーム内に入力された値が残るため、Scanner.next()メソッドでのスキャンが可能
            int n = stdIn.nextInt();

            // 除数として0が入力された場合はArithmeticExceptionが発生
            System.out.println("Ans.: " + (100 / n));
        }

        // catch節 - 例外を捕捉(catch)してエラーハンドリングを行うブロック
        // InputMismatchExceptionが発生した場合の処理(=例外ハンドラ)
        catch (InputMismatchException e) {
            System.out.println("Exception: " + e);

            String s = stdIn.next();

            System.out.println("Omitted: " + s);
        }
        // ArithmeticExceptionが発生した場合の処理(=例外ハンドラ)
        catch (ArithmeticException e) {
            System.out.println("Exception: " + e);
        }

        // finally節 - 例外発生にかかわらず必ず実行されるブロック
        finally {
            System.out.println("End of calc.");
        }
    }
}
```

```java:実行結果①
100 / ABC
Exception: java.util.InputMismatchException
Omitted: ABC
End of calc.
```

```java:実行結果②
100 / 0
Exception: java.lang.ArithmeticException: / by zero
End of calc.
```

# 例外クラス
すべての例外は、`Throwable`クラスの`下位クラス`で定義され、
`詳細メッセージ`である`String`型文字列と、`原因`である`Throwable`オブジェクトで構成される。

また、`Throwable`クラスの`サブクラス`には、以下の2種類のクラスが定義される。

|クラス|内容|
|:--|:--|
|`Error`|プログラムが回復を期待できない重大な例外であり、`捕捉`の必要がない。|
|`Exception`|プログラムが回復を期待できる例外であり、`捕捉`しなければならない。|

ただし、`Exception`クラスの`サブクラス`である`RuntimeException`クラスは
`非検査例外(unchecked exception)クラス`と呼ばれ、`コンパイル`時に検査されないため、`捕捉`する必要はない。

それ以外の`Exception`クラスの`サブクラス`は`検査例外(checked exception)クラス`と呼ばれ、
`コンパイル`時に検査されるため、`捕捉`する必要がある。

# サンプルコード2(例外処理)

```java
import java.util.Scanner;

public class ThrowAndCatch {
    // 検査例外(checked exception)を送出する可能性があるメソッドは"throws"キーワードを付与し、
    // 発生した例外を送出できるようにする必要がある
    static void check (int sw) throws Exception{
        switch (sw) {
            case 0: throw new Exception("This exception has to be catched.");
            case 1: throw new RuntimeException("This exception does not have to be catched.");
        }
    }

    // 検査例外を送出する可能性があるメソッドを呼び出す場合も同様に"throws"キーワードを付与し、
    // 発生した例外を送出できるようにする必要がある
    static void call(int sw) throws Exception{
        check(sw);
    }

    public static void main(String[] args) {
        Scanner stdIn = new Scanner(System.in);

        System.out.print("sw(0 .. checked/1 .. unchecked): ");
        int sw = stdIn.nextInt();

        try {
            call(sw);
        }
        // Exceptionクラスの下位クラスも代入可能であるため、
        // RuntimeExceptionクラスのオブジェクトもここで捕捉される(=ポリモーフィズム)
        // -> 仮引数の型に対して代入可能な例外はすべて捕捉される
        catch (Exception e) {
            // 例外の詳細メッセージを取得
            // -> 動的結合によってオブジェクトの参照先に応じてメソッドが呼び出される
            System.out.println(e.getMessage());
        }
    }
}
```

```java:実行結果
sw(0 .. checked/1 .. unchecked): 0
This exception has to be catched.

sw(0 .. checked/1 .. unchecked): 1
This exception does not have to be catched.
```

```java:throwsキーワードを付与せずExceptionを送出しようとした場合
sw(0 .. checked/1 .. unchecked): 0
Exception in thread "main" java.lang.Error: Unresolved compilation problem: 
        Unhandled exception type Exception
```

***

# サンプルコード(資源付きtry文)

```java:TryWithResource.java
import java.io.*;
import java.util.Scanner;

public class TryWithResource {
    
    static void init() {
        // 資源付きtry文(try-with-resources statement)
        // -> java.lang.AutoClosableインタフェースを実装するリソースの解放処理(本来は記述必須)を自動的に行うtry文
        try (
            BufferedReader br = new BufferedReader( new FileReader("LastTime.txt") );
        ) {
            String input = br.readLine();
            System.out.println("your recent input: " + input);
        }
        catch (IOException e) {
            System.out.println("You have never executed this program.");
        }
    }

    static void write(String input) {
        // 資源付きtry文(try-with-resources statement)
        try (
            FileWriter fw = new FileWriter("LastTime.txt");
        ) {
            fw.write(input);
        }
        catch (IOException e) {
            System.out.println("Something went wrong.");
        }
    }

    public static void main(String[] args) {
        Scanner stdIn = new Scanner(System.in);

        // 呼び出し元メソッドで捕捉処理を記述しているため、try文は不要
        init();

        System.out.print("Input: "); String input = stdIn.nextLine();

        // 呼び出し元メソッドで捕捉処理を記述しているため、try文は不要
        write(input);
    }
}
```

```java:実行結果①
You have never executed this program.
Input: ABC
```

```java:実行結果②
your recent input: ABC
Input: 123
```

***

# 用語集

|用語|内容|
|:--|:--|
|コンポジション(合成)|`インスタンス`が**内部的**に別の`インスタンス`をもつ構造。<br>→クラス`A`が`has-A`関係をもつクラス`B`において、<br>`A`オブジェクトは内部的に`B`オブジェクトをもつ。|
|is-A(kind-of-A)関係|クラス`A`をクラス`B`が継承している場合、クラス`B`は一種のクラス`A`となること。|
|上位/下位クラス(super/sub class)|`祖先/先祖クラス`。|
|直接上位/直接下位クラス(direct super/sub class)|`親/子クラス`。|
|多重継承(multiple inheritance)|複数`クラス`から`派生`を行うこと。|
|ポリモーフィズム(多相性, polymorphism)|`クラス型変数`が派生関係にある`クラスオブジェクト`を参照できること。|
|ハッシュ値(hash code)|個々のインスタンスを区別するために`Object`クラスで定義される識別番号。|
|スタックトレース(stack trace)|`例外(exception)`が`メソッド`を通じて`伝播`すること。|