【问题标题】:Java generics abstract factory issueJava泛型抽象工厂问题
【发布时间】:2012-02-08 10:23:27
【问题描述】:

我正在努力完成这项工作:

public abstract class MapperFactory<M extends TaskMapper<? extends Message, ? extends Message, ? extends TaskForm>> {

    public static <M extends TaskMapper<? extends Message, ? extends Message, ? extends TaskForm>> MapperFactory<M> getMapperFactory(Message msgIn, Message msgOut) {

        if (msgIn.isMyMapper())
            return new MyTaskMapperFactory();

        throw new IllegalStateException("Mapper not found!");
    }

    public abstract TaskMapper<? extends Message, ? extends Message, ? extends TaskForm> getTaskMapper();

    public static class MyTaskMapperFactory extends MapperFactory<MyTaskMapper> {

        @Override
        public TaskMapper<? extends Message, ? extends Message, ? extends TaskForm> getTaskMapper() {
            return new MyTaskMapper();
        }

    }
}

public interface TaskMapper<I extends Message, O extends Message, F extends TaskForm> {

    public F fillForm(I msgIn, O msgOut, F taskForm);

    public O fillMsgOut(F taskForm);
}

public class MyTaskMapper implements TaskMapper<IncomingMessage, OutgoingMessage, MyTaskForm > {

    public MyTaskForm fillForm(IncomingMessage msgIn, OutgoingMessage msgOut,
            MyTaskForm taskForm) {
        return null;
    }

    public OutgoingMessage fillMsgOut(MyTaskForm taskForm) {
        return null;
    }

}

问题是编译错误:

类型不匹配:无法从 MapperFactory.MyTaskMapperFactory 到 映射器工厂

在我的 MapperFactory 中:

if (msgIn.isMyMapper())
            return new MyTaskMapperFactory();

任何想法如何解决这个错误?

当然要替换:

public static <M extends TaskMapper<? extends Message, ? extends Message, ? extends TaskForm>> MapperFactory<M> getMapperFactory(Message msgIn, Message msgOut) {

        if (msgIn.isMyMapper())
            return new MyTaskMapperFactory();

        throw new IllegalStateException("Mapper not found!");
    }

与:

public static MapperFactory<?> getMapperFactory(Message msgIn, Message msgOut) {

        if (msgIn.isMyMapper())
            return new MyTaskMapperFactory();

        throw new IllegalStateException("Mapper not found!");
    }

会起作用,但这不是我想要的答案。

这似乎是通用抽象工厂模式的一个问题。 也欢迎提供使用自定义对象的源示例的答案。

【问题讨论】:

  • MAPPER 不是遵循 Java 约定的好类名。
  • 请让你的类名尽可能小(但仍然清晰)。并将MAPPER 重命名为Mapper?奇怪/冗长的类名只会混淆/混淆问题答案。
  • @his MAPPER 不是类名。 HashMap中的T等泛型Type的名称
  • 它仍然是一个类型名称。 Java 中所有的大写都是常量。
  • @his - 不,不是,没关系......惯例是只使用单个字母,如 BalusC 所述stackoverflow.com/questions/2900881/…,所以我更改了我的代码以遵循惯例。

标签: java generics design-patterns abstract-factory


【解决方案1】:

根据 Effective Java,第 2 版,第 28 条:

如果一个类型参数在方法声明中只出现一次,用通配符替换它。

您的 getMapperFactory 方法仅在返回类型中使用类型参数 M。遵循此建议会给出以下方法签名,并且该方法会编译:

public static MapperFactory<? extends TaskMapper<Message, ? extends Message, ? extends String>> getMapperFactory(Message msgIn, Message msgOut)

编辑:我越看代码,就越觉得 MapperFactory 不应该被参数化。此处代码中没有使用参数,getTaskMapper返回一个TaskMapper。

【讨论】:

  • 更短的,签名可以是public static MapperFactory&lt;?&gt; getMapperFactory()。与MapperFactory 的类签名相比,该方法不限制任何类型参数。 public abstract TaskMapper&lt;?, ?, ?&gt; getTaskMapper() 也是如此。 (也可能是public abstract M getTaskMapper(),无法判断类型参数背后的意图。)“当有疑问时,使用较少的泛型” 可能是一个很好的经验法则。
【解决方案2】:

return 语句适用于类型转换:

return (BpmMapperFactory<MAPPER>)new Bpm007PrepareDocTaskMapperFactory();

尽管以当前形式,该代码永远不会执行,因为 Bpm007PrepareDocTaskMapper 没有扩展 BpmCommonMessageDto,因此 msgIn 不可能是 Bpm007PrepareDocTaskMapper 的实例。

【讨论】:

  • 我编辑了if 部分 - 感谢您提供信息,这还没有完成,这里不相关。有什么办法可以避免强制转换?
【解决方案3】:

我的解决方案是用火尽可能多地杀死泛型:

abstract class MapperFactory<M extends TaskMapper<?, ?, ?>> {

    public static MapperFactory<?> getMapperFactory(Message msgIn, Message msgOut) {
        if (msgIn.isMyMapper()) return new MyTaskMapperFactory();
        throw new IllegalStateException("Mapper not found!");
    }

    public abstract M getTaskMapper();
}


class MyTaskMapperFactory extends MapperFactory<MyTaskMapper> {

    @Override
    public MyTaskMapper getTaskMapper() {
        return new MyTaskMapper();
    }

}


interface TaskMapper<I extends Message, O extends Message, F extends TaskForm> {

    public F fillForm(I msgIn, O msgOut, F taskForm); 

    public O fillMsgOut(F taskForm);

}

class MyTaskMapper implements TaskMapper<IncomingMessage, OutgoingMessage, MyTaskForm> {

    public MyTaskForm fillForm(IncomingMessage msgIn, OutgoingMessage msgOut, MyTaskForm taskForm) {
        return null;
    }

    public OutgoingMessage fillMsgOut(MyTaskForm taskForm) {
        return null;
    }

}

如果你并不真正关心它们是什么或者不需要比类签名更多地限制它们,那么实际上没有必要在使用它的每个方法中重复类的类型参数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多