web-dev-qa-db-ja.com

スーパークラス内からサブクラスの名前を取得する

Entityという名前の基本クラスがあるとしましょう。そのクラスには、クラス名を取得する静的メソッドがあります。

_class Entity {
    public static String getClass() {
        return Entity.class.getClass();
    }
}
_

今、私はそれを拡張する別のクラスを持っています。

_class User extends Entity {
}
_

ユーザーのクラス名を取得したい:

_System.out.println(User.getClass());
_

私の目標は「com.packagename.User」の出力をコンソールに表示することですが、Entityクラスは静的メソッドから直接参照されているため、代わりに「com.packagename.Entity」になります。

これが静的メソッドではない場合、thisクラス内でEntityキーワードを使用することで簡単に解決できます(つまり、return this.class.getClass())。ただし、静的に保つにはこのメソッドが必要です。これにアプローチする方法についての提案はありますか?

67
Matt Huggins

ありえない。静的メソッドは、決して実行時多態性ではありません。これらのケースを区別することは絶対に不可能です。

System.out.println(Entity.getClass());
System.out.println(User.getClass());

それらは同じバイトコードにコンパイルされます(メソッドがEntityで定義されていると仮定)。

さらに、このメソッドをポリモーフィックであることが理にかなっている方法でどのように呼び出すのでしょうか?

40

メソッドを静的にしないでください。問題は、getClass()を呼び出すときに、スーパークラスのメソッドを呼び出していることです。静的メソッドは継承されません。さらに、あなたは基本的にObject.getClass()という名前をシャドウイングしていますが、これは混乱を招きます。

スーパークラス内でクラス名を記録する必要がある場合は、使用します

return this.getClass().getName();

これは、Entityインスタンスがある場合は「Entity」、Userインスタンスがある場合は「User」などを返します。

87
matt b

あなたの質問はあいまいですが、静的メソッドから現在のクラスを知りたいと言うことができる限りです。クラスが相互に継承するという事実は関係ありませんが、説明のためにこの方法で実装しました。

 class Parent {
 public static void printClass(){
 System.out.println(Thread.currentThread()。getStackTrace()[2] .getClassName()); 
} 
} 
 
 publicクラスTest extends Parent {
 public static void main(String [] args){
 printClass( ); 
} 
} 
6
Gilead

これは私のために働く

this.getClass().asSubclass(this.getClass())

しかし、私はそれがどのように機能するのか分かりません。

5
sirolf2009

スーパークラスはサブクラスの存在すら知らず、サブクラスの完全修飾名に基づいて操作を実行する必要はありません。正確なクラスが何であるかに基づいて操作が必要であり、継承によって必要な機能を実行できない場合は、次の行に沿って何かを行う必要があります。

public class MyClassUtil
{
    public static String doWorkBasedOnClass(Class<?> clazz)
    {
        if(clazz == MyNormalClass.class)
        {
            // Stuff with MyNormalClass
            // Will not work for subclasses of MyNormalClass
        }

        if(isSubclassOf(clazz, MyNormalSuperclass.class))
        {
            // Stuff with MyNormalSuperclass or any subclasses
        }

        // Similar code for interface implementations
    }

    private static boolean isSubclassOf(Class<?> subclass, Class<?> superclass)
    {
        if(subclass == superclass || superclass == Object.class) return true;

        while(subclass != superclass && subclass != Object.class)
        {
            subclass = subclass.getSuperclass();
        }
        return false;
    }
}

(テストされていないコード)

このクラスも自身のサブクラスについては知りませんが、Classクラスを使用して操作を実行します。おそらく、実装と密接にリンクしている可能性があります(一般に悪いこと、または悪くない場合は特にgoodではありません)が、このような構造はスーパークラスよりも優れていると思いますそのサブクラスはすべてです。

3
Brian S

なぜ独自のgetClass()メソッドを実装したいのですか?あなただけを使用することができます

_System.out.println(User.class);
_

編集(少し詳しく説明します):メソッドを静的にしたい場合。その場合、サブクラスでもスーパークラスでも、クラス名が必要なクラスのメソッドを呼び出す必要があります。次に、MyClass.getClass()を呼び出す代わりに、_MyClass.class_またはMyClass.class.getName()を呼び出すだけです。

また、Object.getClass()インスタンスメソッドと同じシグネチャを持つstaticメソッドを作成していますが、コンパイルされません。

2
samitgaur
  1. スーパークラスにメンバー文字列変数を作成します。
  2. This.getClass()。getName()を、メンバーのString変数に値を格納するコンストラクターに追加します。
  3. 名前を返すゲッターを作成します。

拡張クラスがインスタンス化されるたびに、その名前は文字列に格納され、ゲッターでアクセスできます。

2
Dawg 'N IT

私のコンテキスト:XMLオブジェクトのサブクラスを持つスーパークラスエンティティ。私の解決策:スーパークラスにクラス変数を作成する

Class<?> claz;

次に、サブクラスで、コンストラクターでスーパークラスの変数を設定します

public class SubClass {
   public SubClass() {
     claz = this.getClass();
   }
}
0

静的メソッドは、特定のオブジェクトではなく、クラスに関連付けられています。

複数のサブクラスが存在する場合、これがどのように機能するかを検討してください。たとえば、管理者もエンティティです。 Entityクラスのみに関連付けられている静的なEntityメソッドは、どのサブクラスが必要かをどのように知るのでしょうか?

あなたは出来る:

  • 既存のgetClass()メソッドを使用します。
  • 静的なgetClass()メソッドに引数を渡し、そのオブジェクトでインスタンスメソッドを呼び出します。
  • メソッドを非静的にし、名前を変更します。
0
Andy Thomas

あなたの質問を正しく理解しているなら、あなたが望むものを達成することができる唯一の方法は、各サブクラスで静的メソッドを再実装することだと思います、例えば:

class Entity {
    public static String getMyClass() {
        return Entity.class.getName();
    }
}

class Derived extends Entity {
    public static String getMyClass() {
        return Derived.class.getName();
    }
}

これにより、必要に応じてpackage.Entityとpackage.Derivedが出力されます。面倒だけど、それがあなたの制約なら...

0
brabster

私がそれを正しく取っている場合、静的メソッドの基本クラスでサブクラスを使用したい場合は、メソッドにクラスパラメータを渡すことでこれを行うことができると思います

class Entity {
    public static void useClass(Class c) {
        System.out.println(c);
        // to do code here
    }
}

class User extends Entity {
}

class main{
    public static void main(String[] args){
        Entity.useClass(Entity.class);
    }
}
0
Dis Honest