1️⃣

Javaクラスの基礎

2024/05/23に公開

概要

「Java SE 11 Programmer II (1Z0-816-JPN) 試験」の出題範囲「Javaの基礎」の自己学習メモになります

final修飾子とstatic修飾子

final修飾子

適用箇所 説明
クラス final指定されたクラスを元に、サブクラスは作成できない
メソッド final指定されたメソッドを元に、オーバーライドできない
変数 final指定された変数は、定数

構文

クラスに適用
[アクセス修飾子] final class class名{ }

メソッドに適用
[アクセス修飾子] final 戻り値の型 メソッド名( 引数 ){ }

変数に適用
[アクセス修飾子] final データ型 変数名 = 初期値;

final修飾子を利用したクラスとメソッドのサンプルコード

class SuperA { }
final class SuperB {}
class SuperC { void print( ){ } }
class SuperD { final void print( ){ } }

class ChildA extends SuperA { } // OK
class ChildB extends SuperB { } // NG
class ChildC extends SuperC { void print(){} } // OK
class ChildD extends SuperD { void print(){} } // NG

static修飾子

クラス内に定義したメンバ間のアクセスルール

  • クラス内で定義したインスタンスメンバ同士、staticメンバ同士は直接アクセスできる
  • クラス内で定義したインスタンスメンバは、クラス内で定義したstaticメンバにアクセスできる
  • クラス内で定義したstaticメンバは、クラス内で定義したインスタンスメンバにアクセスできない

サンプルコード

public class Test {
    int instanceVal;
    static int staticVal;
    int methodA() { return instanceVal; }      // OK
    int methodB() { return staticVal; }        // OK
    static methodC() { return instanceVal; }   // NG
    static methodD() { return staticVal; }     // OK
    static methodE() {                         // OK
        Test obj = new Test();
        return obj.instanceVal;
    }
}

列挙型

values()とvalueOf()メソッド

メソッド名 説明
static 列挙型 values() 列挙した値を全て配列で返す
static 列挙型 valueOf(String name) 引数で指定された名前を持つ値を全て返す

Enumクラスの主なメソッド

メソッド名 説明
final String name() enum定数の名前を返す
String toString() enum定数の名前を返す このメソッドは任意でオーバーライドできるが、nameメソッドはオーバーライドできない
final boolean equals( Object ohter ) 指定されたオブジェクトがこのenum定数と同じ場合は、trueを返す
final int hashCode() enum定数のハッシュコードを返す
static <T extends Enum<T>> T valueOf( Class<T> enumType,String name ) 指定された名前をもつ、指定されたenum方のenum定数を返す
final int ordinal() 列挙宣言での位置を返す

列挙型のポイント

  • 列挙型の定義ではenumキーワードを使用する
  • クラス宣言と同様に、コンストラクタ、メソッド、メンバ変数を定義できる
  • コンパイルするとクラスファイルが生成される
  • 列挙した値を参照するには、「列挙型名.列挙した値」とする
  • newキーワードによるインスタンス化はできない
  • 列挙型によって作成されたクラスはfinalクラスであるため、extendsによる継承はできない
  • 抽象メソッドの利用やインターフェースの実装は可能
  • 列挙型はComparableインターフェースを実装しており、確定数は明記した順番で管理される

Objectクラス

メソッド名 説明
boolean equals( Object obj ) 自オブジェクトとobjectを比較し、同じオブジェクトであればtrueを返す
final Class<?> getClass() このオブジェクトの実行時クラスを返す
int hashCode() オブジェクトのハッシュコードを返す
String toString() オブジェクトの文字列表現を返す

equals()メソッドとhashCode()メソッドのオーバーライド

instanceof演算子

左辺で指定した変数が、右辺で指定した型をもっていればtrueを返す
左辺と右辺が同一の型でなくても、右辺がスーパクラスやインターフェースで、左辺がそのサブクラスや実装クラスであればtrueを返す
左辺と右辺が継承関係がまったくない場合は、コンパイルエラーとなる

インターフェース

インターフェースの特徴

  • 変数を宣言すると、暗黙的にpublic static final修飾子が付与される
  • インターフェースでの抽象メソッドで使用可能なのは、public、abstractのみ
  • インターフェースでの具象メソッドでstaticメソッドは、public、private
  • インターフェースでの具象メソッドでpublicメソッドの場合は、defaultのみ
  • インターフェースでの具象メソッドで非staticメソッドは、privateのみ

staticな具象メソッド

構文

[アクセス修飾子] static 戻り値 メソッド名(引数) { 処理 }

static voide foo() { System.out.println("foo"); }

デフォルトメソッド

構文

[public] default 戻り値 メソッド名(引数) { 処理 }

default void foo() { System.out.println("foo"); }

SE9以降では、privateな具象メソッドも定義できるようになりました

構文

private [static] 戻り値 メソッド名(引数) { 処理 }

private void foo() { System.out.println("foo"); }

インターフェースの継承

構文

[修飾子] class クラス名 implements インターフェース名 { }

public interface Myinterface { } // インターフェース
public class MyClass implements Myinterface { } // 実装クラス

様々な実装クラス

コンパイルエラーになるサンプルコード1

interface A {
    void method(); // 抽象method
}

interface X extends A {
    @Override
    default void method() { System.out.println("X"); }
}

interface Y extends A {
    @Override
    default void method() { System.out.println("Y"); }
}

class MyClass implements X,Y { } // このクラスが原因でコンパイルエラー

MyClassのmethodメソッドが呼び出された際に、XとYのどちらを呼び出せがいいか分からなくなるためコンパイルエラー

コンパイルエラーになるサンプルコード1を解決するサンプルコード1

class MyClass implements X,Y {
    @Override
    default void method() { System.out.println("MyClass"); } 
}

MyClassで更にオーバーライドすればコンパイル、実行可能です

明示的に呼び出すサンプルコード2

class MyClass implements X,Y {
    @Override
    default void method() { X.super.method(); } 
}

クラスが優先されて呼び出されるサンプルコード3

interface A {
    void method();
}

interface X extends A { // Aインターフェースのサブインターフェース
    @Override
    default void method() { System.out.println("X"); }
}

class Y implements A { // Aインターフェースの実装クラス
    @Override
    public void method() { System.out.println("Y"); }
}

class MyClass extends Y implements X { }

public class Main {
    public static void main( String[] args ) {
        MyClass obj = new MyClass();
        obj.method();
    }
}

実行結果

Y

ネストクラス

java言語ではクラス定義の中に、さらにクラスを定義することができます。これをネクストクラスと呼びます

ネストクラスのルール

staticクラス/非staticクラス

  • 外側のクラスと同じ名前(クラス名)は使用できない
  • アクセス修飾子(public、private、protected)を使用できる
  • abstract修飾子、final修飾子を使用できる

staticクラスのみ

  • 非staticメンバ、staticメンバを持つことができる
  • 外側のクラスで定義したインスタンス変数にアクセスできない

非staticクラスのみ

  • staticメンバを持つことができない
  • 外側のクラスで定義したインスタンス変数、static変数にアクセスできる

ネクストクラスのアクセス

構文

非staticクラスの場合
外側のクラス名.非staticクラス名 変数名 = new 外側のクラス名().new 非staticクラス名;

Outer.A a = new Outer.new A();

staticクラスの場合
外側のクラス名.staticクラス名 変数名 = new 外側のクラス名.staticクラス名;

Outer.B b = new Outer.B();

ローカルクラス

ローカルクラスとは、あるクラスのメソッド内に定義したクラスのことです

class Outer {
    void method() {
        class A { // ローカルクラス
        }
    }
}

ローカルクラスのルール

  • アクセス修飾子(public、private、protected)を使用できない
  • static修飾子を使用できない
  • abstract修飾子、final修飾子を使用できる
  • 外側のクラスのメンバにアクセスできる
  • ローカルクラスから外側のクラスのメソッドの引数およびローカル変数にアクセスするには、各変数がfinalでなければならない

匿名クラス

匿名クラスとは、クラス名を指定せずに、クラス定義とインスタンス化を1つの式として記述したクラスのことです

class Outer {
    void method() {
        new スーパクラス名またはインターフェース名() { // 匿名クラス

        }; // セミコロンは必須
    ]
}

匿名クラスのルール

  • アクセス修飾子(public、private、protected)を使用できない
  • static修飾子を使用できない
  • abstract修飾子、final修飾子を使用できない
  • 外側のクラスのメンバにアクセスできる
  • 外側のクラスのメソッドの引数および、ローカル変数にアクセスできる(ただし、暗黙的にfinalであること)

Discussion