【问题标题】:Java Generics & jOOQ - How can I create a HashMap of one jOOQ column to anotherJava 泛型和 jOOQ - 如何创建一个 jOOQ 列到另一个列的 HashMap
【发布时间】:2017-07-12 22:03:59
【问题描述】:

我有一个界面

public interface HistoryDao<B extends UpdatableRecord<B>, H extends UpdatableRecord<H>> extends TableDao<H>{
    default void saveHistoryForIds(List<Integer> ids) {
        HashMap<? extends TableField<H, ? extends TableField<H, ? extends Serializable>>, ? extends TableField<B, ? extends TableField<B, ? extends Serializable>>> mappings = setUpHistoryMapping();

        List<? extends TableField<H, ? extends Serializable>> tableFields = new ArrayList<>(mappings.keySet());

        ArrayList<H> hs = new ArrayList<>();
        jooq()
            .insertInto(table(), tableFields);

    }

    HashMap<? extends TableField<H, ? extends TableField<H, ? extends Serializable>>, ? extends TableField<B, ? extends TableField<B, ? extends Serializable>>> setUpHistoryMapping();
}

(TableDao 是一个接口,但不是很重要)

在我的具体课程中,我尝试实现

MyClassHere implements HistoryDao<ApprovalWorkflowRecord, ApprovalWorkflowHistoryRecord>

@Override
public HashMap<? extends TableField<ApprovalWorkflowHistoryRecord, ? extends TableField<ApprovalWorkflowHistoryRecord, ? extends Serializable>>, ? extends TableField<ApprovalWorkflowRecord, ? extends TableField<ApprovalWorkflowRecord, ? extends Serializable>>> setUpHistoryMapping() {
    HashMap<? extends TableField<ApprovalWorkflowHistoryRecord, ? extends TableField<ApprovalWorkflowHistoryRecord, ? extends Serializable>>, ? extends TableField<ApprovalWorkflowRecord, ? extends TableField<ApprovalWorkflowRecord, ? extends Serializable>>> x = new HashMap<>();

    TableField<ApprovalWorkflowHistoryRecord, Integer> id = APPROVAL_WORKFLOW_HISTORY.ID;

    x.put(id, APPROVAL_WORKFLOW.ID);
}

我认为我的问题与协方差有关......(也许)但我不断收到此错误

x.put(id, APPROVAL_WORKFLOW.ID);

method Map.put(CAP#1,CAP#2) is not applicable
  (argument mismatch; TableField<ApprovalWorkflowHistoryRecord,Integer> cannot be converted to CAP#1)

method AbstractMap.put(CAP#1,CAP#2) is not applicable
  (argument mismatch; TableField<ApprovalWorkflowHistoryRecord,Integer> cannot be converted to CAP#1)

method HashMap.put(CAP#1,CAP#2) is not applicable
  (argument mismatch; TableField<ApprovalWorkflowHistoryRecord,Integer> cannot be converted to CAP#1)   where CAP#1,CAP#2 are fresh type-variables:
CAP#1 extends TableField<ApprovalWorkflowHistoryRecord,? extends TableField<ApprovalWorkflowHistoryRecord,? extends Serializable>> from capture of ? extends TableField<ApprovalWorkflowHistoryRecord,? extends TableField<ApprovalWorkflowHistoryRecord,? extends Serializable>> CAP#2 extends TableField<ApprovalWorkflowRecord,? extends TableField<ApprovalWorkflowRecord,? extends Serializable>> from capture of ? extends TableField<ApprovalWorkflowRecord,? extends TableField<ApprovalWorkflowRecord,? extends Serializable>>

【问题讨论】:

    标签: java inheritance jooq


    【解决方案1】:

    如果您忽略所有(令人印象深刻的)通用噪音,您的问题归结为使用通配符将值放入集合中的经典问题:

    Map<?, ?> x = new HashMap<>();
    x.put("a", "b"); // Doesn't work.
    

    只需删除所有不需要的通配符并用具体类型替换它们。作为一般经验法则:

    • 在方法参数中使用通配符以允许方法调用者传递一些不太具体的集合。
    • 将泛型类型放入集合时使用通配符,例如List&lt;Class&lt;?&gt;&gt; 或在本例中为 List&lt;TableField&lt;H, ?&gt;&gt;
    • 尽量避免从方法中返回通配符。

    以下是在您的情况下解决此问题的方法:

    public interface HistoryDao<
        B extends UpdatableRecord<B>, 
        H extends UpdatableRecord<H>
    > extends TableDao<H> {
        default void saveHistoryForIds(List<Integer> ids) {
            HashMap<TableField<H, ?>, TableField<B, ?>> mappings = setUpHistoryMapping();
            List<TableField<H, ?>> tableFields = new ArrayList<>(mappings.keySet());
            jooq().insertInto(table(), tableFields);
        }
    
        HashMap<TableField<H, ?>, TableField<B, ?>> setUpHistoryMapping();
    }
    
    class MyClassHere implements HistoryDao<
        ApprovalWorkflowRecord, 
        ApprovalWorkflowHistoryRecord
    > {
    
        @Override
        public HashMap<
            TableField<ApprovalWorkflowHistoryRecord, ?>, 
            TableField<ApprovalWorkflowRecord, ?>
        > setUpHistoryMapping() {
            HashMap<
                TableField<ApprovalWorkflowHistoryRecord, ?>, 
                TableField<ApprovalWorkflowRecord, ?>
            > x = new HashMap<>();
    
            x.put(APPROVAL_WORKFLOW_HISTORY.ID, APPROVAL_WORKFLOW.ID);
        }
    }
    

    我改变了什么?

    • 本地Map 类型不再在其键/值上使用通配符。而不是Map&lt;? extends TableField&lt;...&gt;, ? extends TableField&lt;...&gt;&gt;,只写Map&lt;TableField&lt;...&gt;, TableField&lt;...&gt;&gt;
    • setUpHistoryMapping() 方法的返回类型也是如此。
    • 这里不需要? extends Serializable。该类型绑定不会增加任何价值。请改用?
    • 您无意中嵌套了TableField&lt;?, TableField&lt;...&gt;&gt;。这在 jOOQ 环境中没有意义。

    另见:

    【讨论】:

    • 是的!太感谢了。我肯定在外卡上挣扎了很多,这很有意义。也感谢您提供所有其他信息!
    猜你喜欢
    • 1970-01-01
    • 2018-07-23
    • 2020-04-01
    • 2019-05-16
    • 2017-12-13
    • 1970-01-01
    • 2014-01-07
    • 1970-01-01
    • 2017-12-30
    相关资源
    最近更新 更多