【问题标题】:Dynamic Casting in a Loop循环中的动态投射
【发布时间】:2016-03-11 23:20:24
【问题描述】:

很难解释我在这里想要达到的目标(所以......抱歉,如果我在搜索中错过了一个明显的答案)......

我正在尝试基于与 HashMap 中的值配对的类动态实例化对象。但是,我一直在寻找一种真正有效的方法时遇到问题。目前,我正在做这样的事情:

HashMap<String, Flag<?>> flags = new HashMap<String, Flag<?>>();
HashMap<String, Class> keys = new HashMap<String, Class>();

keys.put("test", BooleanFlag.class);
keys.put("thing", StringFlag.class);
keys.put("foo", DoubleFlag.class);

for (Map.Entry<String, Class> key : keys.entrySet()) {
    try {
        Class c = key.getValue();
        Object obj = c.getConstructor(String.class, String.class).newInstance(key.getKey(), "test value that will be checked and coerced by one of the flag classes");
        flags.put(key.getKey(), c.cast(obj));
    } catch (Exception ex) {
        //exception handling
    }
}

在该方法的当前化身中,c.cast(obj) 会抛出一个编译器错误,说明在期望标志的位置找到了一个对象。我是不是要解决这个可怕的错误/这可能吗?

【问题讨论】:

  • 为什么不存储 Builder 对象而不是 BooleanFlag。 BuilderObject 可以知道它应该创建什么类型,并且您不需要强制转换。或者有一个工厂来创建你的对象并将密钥作为标志传递给你做什么?

标签: java


【解决方案1】:

你可以的

if(obj instanece of Flag) {
  flags.put(key.getKey(), (Flag)obj);
}

这应该处理Flag的所有子类/实现

【讨论】:

  • 我不需要将其转换回 BooleanFlag 或 StringFlag 以访问更具体的子类的成员方法吗?这是我需要避免的事情,因此为什么我使用 Flag> 泛型而不是首先转换为 Flag。
  • 是的,但前提是这些方法不是Flag 的一部分。如果您要遍历 flags 映射的值,您可以使用 valies 作为 Flag 或去 checkijg 获取某些细节的 instanceof。如果您详细说明 StringFlag 与 Flag 的不同之处?
  • Flag 是一个抽象类。 StringFlag 是最简单的,只接受给它的值。其他的,如 BooleanFlag,解析给它们的字符串值并设置规范值(在 BooleanFlag 的情况下为布尔值,在另一种标志类型的情况下为笛卡尔坐标等)。
  • 但是你会如何使用它们?如果您知道这是 BooleanFlag,您还想调用哪些其他(公共)方法?
  • 嗯...这是一个好点。我认为所有公开的东西都应该在抽象类中。在边缘情况下应该仍然可以用 instanceof 戳它......
【解决方案2】:

“工厂模式”可能是您真正需要的吗?

public class Flag<T> {}

public interface FlagFactory<T> {
    public Flag<T> newInstance();
}

public class BooleanFlagFactory implements FlagFactory<Boolean> {
    public Flag<Boolean> newInstance() {
        return new Flag<Boolean>();
    }
}
public class StringFlagFactory<T> implements FlagFactory<String> {
    public Flag<String> newInstance() {
        return new Flag<String>();
    }
}

HashMap<String, FlagFactory> factories = new HashMap<String, FlagFactory>();

public void test() {
    factories.put("test", new BooleanFlagFactory());
    factories.put("thing", new StringFlagFactory());

    Flag flag = factories.get("test").newInstance();

}

【讨论】:

  • 我想我会按照这些思路去做。我认为无论如何最好避免反思。
猜你喜欢
  • 2015-12-23
  • 2012-05-14
  • 2014-11-16
  • 1970-01-01
  • 2020-10-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-01
相关资源
最近更新 更多