35

実装するクラスに基づいて2つのオブジェクトを比較する必要がありますか?getClass()いつ使用して比較するのgetClass().getName()か?2つのObjectsクラスタイプ(名前)を比較するこのアプローチに違いはありますか?

public abstract class Monster { ... }
public class MonsterTypeOne extends Monster { ... }
public class MonsterTypeTwo extends  Monster { ... }

    Monster monster = MonsterTypeOne();
    Monster nextMonster = MonsterTypeTwo();


if(nextMonster.getClass().getName().equals(monster.getClass().getName()) )// #1

if(nextMonster.getClass().equals(monster.getClass()) )// #2

編集1


どうですか:?

nextMonster.getClass().equals(MonsterTypeOne.class)
4

7 に答える 7

35

使用class.equals()

if (nextMonster.getClass().equals(monster.getClass()))

または、各クラスはシングルトンのようなものであるため(クラスローダーごとに各クラスのインスタンスは1つだけであり、ほとんどのJVMにはクラスローダーが1つしかない)、ID比較を使用することもできます。

if (nextMonster.getClass() == monster.getClass())
于 2012-05-05T19:33:54.690 に答える
21

2つのObjectsクラスタイプ(名前)を比較するこのアプローチに違いはありますか?

はい。2つのクラスが異なるによってロードされる場合、2つのクラスは同じ名前を持つ可能性がありますClassLoader

「Javaクラスローダーの基本」

最も単純なクラスローダーは、文字列名で参照されるクラス本体のフラットな名前空間を作成します。

「Eclipse-2つのVM(および多くのクラスローダー)の話」は言います

つまり、2つの別々のClassLoaderがあれば、同じ名前の2つのクラスを一度にVMにロードすることができます。


getClass()いつ使用して比較するのgetClass().getName()か?

2つのオブジェクトが同じタイプであるかどうかを知りたい場合は、equalsメソッドを使用して2つのクラス(最初のオプション)を比較する必要があります。

なぜこれを実行したいのか想像できませんが、異なる具象タイプの2つのオブジェクトが同じ完全修飾名のタイプを持っているかどうかを知りたい場合は、2番目を使用できます。Javaのコンテキストで「具象型」と「完全修飾名」を理解していない場合は、Javaの型分析コードを記述していないので、理解したくありません。

于 2012-05-05T19:33:43.627 に答える
3

.equalsを使用して2つのクラスを比較する際に問題が発生しました。上記の解決策は完全に正確ではありません。クラスはComparableを実装していません。

複数のClassLoaderを持つことができるため、クラス参照は必ずしもJVM内の真のシングルトンではありません。

コンパイル後にBeanからアノテーションを掘り出すMavenプラグインを書いていました。プラグインには1つのクラスローダーがあり、私には独自のクラスローダーがありました。異なるローダーからの同じ名前の2つのクラスを比較する場合、比較は失敗します。

Object.equalsの実装は次のようになります。

public boolean More ...equals(Object obj) {
       return (this == obj);
}

したがって、参照を比較します。

クラスを比較していて、関係するクラスローダーが1つだけであることが確実にわかっている場合は、.equalsまたはc1 == c2を安全に使用できますが、名前で比較する必要があるかどうかわからない場合は、次のようにします。

if(c1.getName().equals(c2.getName()) {
   ...
}
于 2015-10-07T17:51:00.557 に答える
1

実際のところ、信頼できるクラスを名前で比較することは弱点です。https://cwe.mitre.org/data/definitions/486.htmlを参照してください

if (nextMonster.getClass() == monster.getClass())

クラスを比較する正しい方法です

if (nextMonster.getClass().equals(monster.getClass()))

@Bohemianが言及したのと同じ理由でまだ機能するはずです

于 2015-12-13T13:33:31.100 に答える
0

同じことを実現する別の方法は、サブクラスのハッシュコードをオーバーライドすることです。

public interface Parent {
}

public static class Child1 implements Parent{
    private String anyfield="child1";

    @Override
    public int hashCode() {
        //Code based on "anyfield"
    }

    @Override
    public boolean equals(Object obj) {
        //equals based on "anyfield"
    }
}

public static class Child2 implements Parent{
    private String anyfield="child2";

    @Override
    public int hashCode() {
        //Code based on "anyfield"
    }

    @Override
    public boolean equals(Object obj) {
        //equals based on "anyfield"
    }
}

これで、実装/サブクラスが同じ具象型の場合、equalsが返されます。

public static void main(String args[]){
    Parent p1=new Child1();
    Parent p2=new Child1();
    Parent p3=new Child2();
    System.out.println("p1 and p2 are same : "+p1.equals(p2));
    System.out.println("p2 and p3 are same : "+p2.equals(p3));
}

出力-

p1 and p2 are same : true
p2 and p3 are same : false
于 2016-07-01T11:15:56.620 に答える
-1

クラスの組み込みメソッドを使用できます:

if(nextMonster.getClass().isAssignableFrom(monster.getClass()))
于 2020-04-17T11:22:32.570 に答える
-1

getClass().getComponentType()コンテンツタイプを比較するために配列を使用する場合

jshell> var array1 = new int[15]
array1 ==> int[15] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }

jshell> var array2 = new int[10]
array2 ==> int[10] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }

jshell> array1.getClass() == array2.getClass()
$7 ==> true

jshell> array1.getClass().getComponentType()
$8 ==> int

jshell> array1.getClass().getComponentType() == int.class
$12 ==> true
于 2020-11-05T07:19:56.577 に答える