如何在不使用 JAVA 中的 instanceof 的情况下转换为对象 class 的 subclass?

How cast to subclass of object class without use instanceof in JAVA?

我在从扩展对象 class 转换到它的子对象 class 时遇到问题。 遵循此代码模板。

public class Athletic1 extends Object {
      public void run(){
              // run 5km
      }         
}

public class Athletic2 extends Object {

      public void run(){
            // run 10km
      }
}

class SpecificClass{
      // receive an athletic
      SpecificClass(Object obj){
            // HERE i like do something as
            // The left side dont Work
            (obj.getClass().getName) nameVariable = (obj.getClass().getName()) obj;
       }
}

class Main{
    public static void main(String[] args){
          Athletic1 a1 = new Athletic1();
          Athletic2 a2 = new Athletic2();
          SpecificClass sc1 = new SpecificClass(a1);
          SpecificClass sc2 = new SpecificClass(a2);
    }
}

我可以求助于 instanceOf,但是当我有很多 subclass 数量的 Object 时,代码会变得非常庞大。有替代方案吗?

        // Supose that i hava 10 Athletic Class
        // I have that do this????????
        if (obj instanceOf Athletic1)
             Athletic1 a1 = (Athletic1) obj;
        ...
        ...
        else{
             Athletic1 a10 = (Athletic10) obj;
        }

有人可以帮助我吗? 谢谢

无法像您尝试的那样以动态方式使用类型转换。以下是您尝试做的一些问题:

(obj.getClass().getName()) obj;

方括号内的"stuff"必须是标识符而不是表达式。该标识符需要是实际 class 的名称或编译时已知的实际接口。它不能是变量的标识符。它甚至不能是类型参数的标识符。

(obj.getClass().getName) nameVariable = ...

这是完全错误的。没有语法允许您像这样在赋值的左侧使用类型转换。


那么是否有可能 "subclass" 实例避免使用 instanceof

instanceof 未用于执行子classing。类型转换就是这样做的! instanceof实际上是用来区分子class的。

不使用 instanceof.

进行区分是可能的(尽管可能不是您想要的!)
  1. 在 class 名称上使用 switch

    switch (obj.getClass().getName()) {
    case "a.b.Athletic1":
        Athletic1 a1 = (Athletic1) obj;
        // do stuff
        break;
        ...
    case "a.b.Athletic10":
        Athletic10 a10 = (Athletic10) obj;
        // do stuff
    }
    

    问题:您仍然有样板代码来区分固定数量的案例。

  2. 使用 Map.

    Map<Class<?>, Consumer<?>> mapping = new Map<> {{
        put(a.b.Athletic1.class, 
            o -> {
                Athletic1 a1 = (Athletic1) o;
                // do stuff
            });
        put(a.b.Athletic10.class, 
            o -> {
                Athletic10 a10 = (Athletic10) o;
                // do stuff
            });
    }};
    
    Consumer<Object> c = mapping.get(obj.getClass());
    if (c != null) {
        c.accept(obj);
    }
    

    优点:

    • 地图可以动态填充。
    • 如果需要 Consumer 对象可以动态创建为代理 classes。 (虽然很贵!)

    缺点:仍然有很多样板。

虽然这些避免了明确的 instanceof,(IMO)这些与您现有的方法一样糟糕。 "code smell" 仍然存在。


IMO,真正的解决方案是使用 Java 多态性。

  1. Athleticclasses.

  2. 创建一个commons superclass/接口
  3. 在superclass/接口中创建一个表示动作的方法

  4. 在每个 Athletic class 中实现操作方法。

  5. 称之为...