DEV Community

TANIAOKA, Akihiro
TANIAOKA, Akihiro

Posted on

3章10

画像に表示されているJavaのコードは、SampleクラスとMainクラスから成り立っており、Sampleクラスにはequalsメソッドが定義されています。このequalsメソッドはオブジェクト間の等価性を判定するために用いられます。コメントアウトを加えてコードを説明します。

// Sampleクラスの定義
public class Sample {
    // numというプライベートな整数型の変数をクラス内に宣言
    private int num;

    // コンストラクタ。Sampleオブジェクトを生成するときに整数を受け取り、num変数を初期化する
    public Sample(int num) {
        this.num = num; // このオブジェクトのnum変数に引数の値を設定する
    }

    // equalsメソッド。Sample型のオブジェクトを引数に取り、等価性を判定する
    public boolean equals(Sample obj) {
        if (obj == null) { // 引数で受け取ったオブジェクトがnullであれば、falseを返す
            return false;
        }
        return this.num == obj.num; // このオブジェクトのnumと引数のオブジェクトのnumが等しいか判定し、結果を返す
    }
}

// Mainクラスの定義
public class Main {
    // mainメソッド。プログラム実行時に呼び出される
    public static void main(String[] args) {
        Object a = new Sample(10); // Sampleオブジェクトを生成し、aに代入(10を渡している)
        Object b = new Sample(10); // 別のSampleオブジェクトを生成し、bに代入(こちらも10を渡している)
        System.out.println(a.equals(b)); // aとbの等価性を判定し、結果をコンソールに出力する
    }
}
Enter fullscreen mode Exit fullscreen mode

Mainクラスのmainメソッドでは、Sampleオブジェクトabが作成されています。それぞれに10がコンストラクタを通してnum変数に設定されます。次にa.equals(b)が呼び出され、abnumの値が等しいか比較されます。

このコードの答えがD、すなわち[false]と表示される理由は、equalsメソッドがオーバーライドされておらず、Objectクラスのデフォルトのequalsメソッドが使用されているからではありません。実際には、Sampleクラスでequalsメソッドがオーバーライドされており、abは同じnumの値(10)を持っているため、このメソッドはtrueを返すはずです。ただし、問題はObject型の変数にSampleオブジェクトが割り当てられており、equalsメソッドがSampleのものとして呼び出されないことです。これはObjectクラスのequalsメソッドが呼び出されるため、参照の同一性(つまり、両方の参照がまったく同じオブジェクトを指しているかどうか)をチェックするので、falseを返すことになります。

しかし、通常であればSampleクラスのequalsメソッドが正しくオーバーライドされていて

、かつabSample型として宣言されていれば、trueが出力されるはずです。したがって、コードの意図された挙動と問題の答えには矛盾があります。コードが正しい挙動を示すように、abSample型で宣言する必要があります。

Sample a = new Sample(10); // Sample型として宣言
Sample b = new Sample(10); // Sample型として宣言
Enter fullscreen mode Exit fullscreen mode

このように宣言すれば、a.equals(b)trueを返し、コンソールにtrueが出力されるはずです。ですので、問題文の指定や答えに何らかの誤りがあるか、あるいは追加の文脈が必要かもしれません。

追記

Javaにおいて、equalsメソッドを正しくオーバーライドするためには、Objectクラスのequalsメソッドのシグネチャに合わせて、引数としてObject型を取る必要があります。また、メソッドがオーバーライドされていることを明示するために@Overrideアノテーションを使用するのが一般的です。

以下はSampleクラスでequalsメソッドを正しくオーバーライドする方法です:

public class Sample {
    private int num;

    public Sample(int num) {
        this.num = num;
    }

    // Objectのequalsメソッドをオーバーライド
    @Override
    public boolean equals(Object obj) {
        // まずは同じインスタンスであるかをチェック
        if (this == obj) {
            return true;
        }
        // 引数がnullであるか、または異なるクラスのインスタンスであれば、falseを返す
        if (obj == null || getClass() != obj.getClass()) {
            return false;
        }
        // 引数をSample型にキャスト
        Sample sample = (Sample) obj;
        // numの値を比較して等価性を判定
        return this.num == sample.num;
    }
}
Enter fullscreen mode Exit fullscreen mode

このコードでは、まずthis == objによって同じインスタンスであるかどうかをチェックしています。これはパフォーマンス最適化のための短絡的なチェックです。その後、objnullでないか、またこのオブジェクトが属するクラスとobjが属するクラスが同じであるかどうかをチェックしています。このチェックによって、異なるクラスのインスタンス間での等価性比較を回避しています。最後にobjSample型にキャストしてからnumの値を比較しています。

正しくオーバーライドされたequalsメソッドを使用すると、Sampleオブジェクト間での等価性比較が適切に行われるため、a.equals(b)trueを返すことになります(abが同じnumの値を持っている場合)。

Top comments (0)