【问题标题】:How to dynamically create an object for an abstract class without casting?如何在不强制转换的情况下为抽象类动态创建对象?
【发布时间】:2021-06-24 00:59:07
【问题描述】:

我在 JAVA 中有一个抽象类和几个子类。我有一个返回这些子类之一的实例的函数。我不想检查 if...else 以根据返回类型创建对象。需要在运行时动态执行。这个solution 对我没有帮助
ReplaceExpression 是一个重载函数,它返回不同的子类。

 // Expression is abstract class, A and B is subclass\
 // this return me null because i did not make a new object for e1, I know a subclass of Expression
       
   

Expression e1 = ReplaceExpression(1);
Expression e2 = ReplaceExpression("a");

    
    public Expression ReplaceExpression(int i)
    {
    Return new A();
    }
    
    public Expression ReplaceExpression(String s)
    {
    Return new B();
    }

我可以这样做,但我需要更清洁的解决方案:

if (ReplaceExpression(x).getClass().getSimpleName() == "A")
Expression e1 = new A();

所以我的问题是:有没有我可以为我的抽象类实例化一个新的子类而无需硬编码或强制转换?动态或反射之类的东西

【问题讨论】:

  • 你能显示minimal reproducible example吗? ReplaceExpression 是做什么的?
  • 是的,这既可以动态完成,也可以通过反射完成(将每种类型的 Supplier<Expression> 存储在 Map 中,然后根据您用来确定类型的任何内容查找供应商;或者以许多不同的方式使用反射)。但我们需要更多关于您如何确定类型以及链接解决方案为何不适合您的信息。
  • ReplaceExpression 返回什么?如果它返回null,当你调用getClass() 时会有NPE。如果它返回一些东西,只需使用该返回值。
  • @Sweeper 我刚刚编辑:替换是一个函数,在运行时返回子类之一。根据输入参数,它将返回其中一个潜艇。但我不想检查大量代码来转换或实例化特定类型。
  • @zhh 我做到了,问题是 e1 是抽象类,只是返回一个子类使其为 NULL,我必须实例化一个以“new”作为基本解决方案的子类

标签: java design-patterns reflection abstract-class instantiation


【解决方案1】:

如果我理解正确,您可以通过反思来做到这一点。

假设你有Param 类和Expression 类:

abstract class Param {
    public abstract Class<? extends Expression> getTargetClass();
}

class Sub1 extends Param {
    @Override
    public Class<? extends Expression> getTargetClass() {
        return A.class;
    }
}

class Sub2 extends Param {
    @Override
    public Class<? extends Expression> getTargetClass() {
        return B.class;
    }
}

class A extends Expression {
    public A() {}
}

class B extends Expression {
    public B() {}
}

你需要一个方法告诉你要创建哪个类,比如getTargetClass

然后在你的ReplaceExpression 方法中:

public Expression ReplaceExpression(Param x) throws Exception {        
    Class<? extends Expression> cls = x.getTargetClass();
    Constructor<? extends Expression> con = cls.getConstructor();
    return con.newInstance();
}

虽然你可以这样做,但这不是一个好的解决方案,只需使用 if 语句:

public Expression ReplaceExpression(Param x) {
    if (x instanceof Sub1)
        return new A();
    if (x instanceof Sub2)
        return new B();
    return null;
}

更新

您似乎想根据返回的Expression 创建一个新的Expression。您可以使用反射:(仍然不推荐)

Class<? extends Expression> cls = ReplaceExpression(x).getClass();
Constructor<? extends Expression> con = cls.getConstructor();
Expression e1 = con.newInstance();

【讨论】:

  • 感谢您的回答,但我认为我没有解释清楚。我的问题在于这行代码: Expression e1 = ReplaceExpression(x);假设 ReplaceExpression 知道要返回什么。但是这段代码给了我 e1 为空,因为我通常必须说“e1 = new Expression()”来创建新对象。对?但我不能导致 Expression 是抽象类。所以问题不在于如何从 ReplaceExpression 发送对象。不过谢谢
  • 这对我有用,但我不明白你为什么提到不推荐,谢谢
  • 有很多关于这个的文章。如this
猜你喜欢
  • 2011-02-10
  • 1970-01-01
  • 2020-03-08
  • 2014-06-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-29
  • 2012-04-18
相关资源
最近更新 更多