【问题标题】:How to find out the subclass from the base class instance?如何从基类实例中找出子类?
【发布时间】:2011-02-20 19:37:10
【问题描述】:

有没有办法从基类实例中找出派生类的名称?

例如:

class A{
    ....
}
class B extends A{
    ...
}
class c extends A{
    ...
}

现在如果一个方法返回一个A的对象,我能查出它是B还是C类型?

【问题讨论】:

  • 请注意,type sniffing 有点代码味道。做这件事并不总是错误的,但它经常是错误的方法,你应该仔细看看你的设计。如果可能,请依赖多态性(但另请参阅 Steve Yegge 的 When Polymorphism Fails)。
  • baseInstance.getClass().getName()

标签: java oop reflection inheritance


【解决方案1】:

使用instanceofClass#getClass()

A returned = getA();

if (returned instanceof B) { .. }
else if (returned instanceof C) { .. }

getClass() 将返回:A.classB.classC.class

在 if 子句中,您需要向下转换 - 即

((B) returned).doSomethingSpecificToB();

也就是说,有时认为使用instanceofgetClass() 是一种不好的做法。您应该使用polymorphism 来尽量避免检查具体子类的需要,但我无法根据给出的信息告诉您更多信息。

【讨论】:

  • 在这种情况下使用多态性的注意事项:您可以在 A 的实现中拥有一个方法 getType() 或类似的东西,并在 BC 中覆盖该方法。由于 Java 中的所有方法都是虚拟的,因此对 getType() 的调用将解析特定的子类型。
【解决方案2】:

您是否尝试过使用instanceof

例如

Class A aDerived= something.getSomethingDerivedFromClassA();

if (aDerived instanceof B) {

} else if (aDerived instanceof C) {

}

//Use type-casting where necessary in the if-then statement.

【讨论】:

    【解决方案3】:

    简单回答你的问题

    有没有办法从基类对象中找出派生类的名称?

    ,超类无法告诉子类的名称/类型。

    您必须询问对象(它是子类的一个实例)并询问它是否是:instanceof 一个特定的子类,或者称它为 getClass() 方法。

    【讨论】:

      【解决方案4】:

      你可以在子类的构造函数中做到这一点

      class A {
          protected String classname;
          public A() { this.classname = "A"; }
          public String getClassname() { return this.classname; }
      }
      class B extends A {
          public B() {
              super();
              this.classname = "B";
          }
      }
      

      所以

      A a = new A();
      a.getClassname(); // returns "A"
      B b = new B();
      b.getClassname(); // returns "B"
      ((A)b).getClassname(); // Also returns "B"
      

      因为它被转换为“A”对象,所以它会调用“A”getClassname() 函数,但会返回一个由“B”构造函数设置的值。

      注意:设置前调用super();

      【讨论】:

        【解决方案5】:

        我能想到的方法有两种 1) 一个使用 Java 反射 API 2) 另一个是instanceOf

        其他方法可以是比较对象到对象,我不知道是怎么回事,你可以试试这个

        【讨论】:

          【解决方案6】:

          有没有办法从基类实例中找出派生类的名称?

          正如here 的回答,您可以使用这种非常简单的方法。

          abstract class A {
              public final String getName() {
                   return this.getClass().getName();
              }
          }
          
          class B extends A { }
          
          class C extends A { }
          

          然后只需打印当前的class 名称:

          B b = new B();
          C c = new C();
          
          System.out.println(b.getName());
          System.out.println(c.getName());
          

          输出:

          com.test.B
          com.test.C
          

          无需额外存储Strings,查看instanceofoverride任何子类中的方法。

          【讨论】:

            【解决方案7】:

            一种更现代的方法(Java 16+)是对 instanceof 运算符使用模式匹配。语法很简单:

            if(x instanceof X xChild){
                // use xChild
            }
            

            它更短且不易出错,因为它结合了测试变量的运行时类型(上例中的x)、强制转换并将其分配给新变量(`xChild)的所有步骤在上面的例子中)。 Read more.

            另一个例子:

                public void addUIControl(UIControl control) {
                    if(control instanceof SelectList sl){
                        selectList = sl;
                    }
                    else if(control instanceof TextBox tb){
                        textBox = tb;
                    }
                    else if(control instanceof Button btn){
                        button = btn;
                    }
                    else {
                        throw new IllegalArgumentException("Uknown UIControl object has been passed to the SendFormMediator");
                    }
                }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-11-02
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2013-10-15
              • 1970-01-01
              相关资源
              最近更新 更多