どのように私はセッターの周りに一般化メソッドを作成するのですか?

オキシ:

私は20+のフィールドを持つDynamoDBの上でDAOを定義したいです。Javaでは、私は、定型コードの束を避けるために、ロンボクを使用して、このような何かを行うことができます。

@Setter
@Getter
@DynamoDBTable("MyTable")
public class MyDAO {
    //FIELD_1, FIELD_2, FIELD_3 defined as static final String elsewhere

    @DynamoDBAttribute(attribute = FIELD_1) 
    private final String field1;

    @DynamoDBAttribute(attribute = FIELD_2)
    private final Long field2;

    @DynamoDBAttribute(attribute = FIELD_3)
    private final int field3;
    ...
}

問題は、私は次のような各フィールドのために何かをした方法を持っていた場合はステップ2でセッターは異なるだろうし、ステップ3でフィールド名が異なることになるので、私は、何度も何度も、コードを複製終わるだろう(すなわちsetField1第一およびsetField2)秒間。

public void addField1(String key, String field1Value) {
    //Wrap some retry logic and error handling around the following
    // 1. get DAO for key
    // 2. set FIELD_1 to field1Value in DAO if not set
    // 3. put DAO in DynamoDB using attribute name FIELD_1
}

public void addField2(String key, Long field2Value) {
    //Wrap some retry logic and error handling around the following
    // 1. get DAO for key
    // 2. set FIELD_2 to field2Value in DAO if not set
    // 3. put DAO in DynamoDB using attribute name FIELD_2
}

理想的には、私のような何かがしたいaddField、私はすべてのフィールドのためにすべてを複製する必要はありませんので、すべての再試行ロジックで、以下の方法を。

private void addField(String fieldName, String key, Object value);

public void addField1(String key, String field1Value) {
    addField(FIELD_1, key, (Object) field1Value);
}

私は、次のようなフィールド名とBiConsumers間のマップを試してみました

Map<String, BiConsumer<MyDAO, Object>> setterMap = 
    new HashMap<String, BiConsumer<MyDAO, Object>>(){{ 
        put(FIELD_1, MyDAO::setField1);
        put(FIELD_2, MyDAO::setField2);
    }};

private void addField(String fieldName, String key, Object value) {
    ...
    // 2. Use setterMap.get(fieldName).accept(value);
    ...
}

問題は、私は、私はキャストすることはできませんというエラーを取得されBiConsumer<MyDAO, String>にをBiConsumer<MyDAO, Object>

種類ごとに別々のマップやメソッドを作成する - それはそれを行うための唯一の方法ですか?それともこれを行うにはよりエレガントな方法は何ですか?

トマシュLinkowski:

まあ、私はそれが使用して行うことは可能だとは思わないMap 場合、あなたは型の安全性を維持したいです。代わりに、ここで私はどうなるのかです:

1)私はそのような特別なクラスを作成したいです:

@AllArgsConstructor
@Getter
final class FieldDefinition<T> {

    private final String name;
    private final BiConsumer<MyDAO, T> setter;
}

2)次に、私がで定数を作成したいMyDAO、でも良く、近くにいくつかのヘルパーオブジェクト内(またはMyDAO)そのような:

static final FieldDefinition<String> FIELD_1_DEF = new FieldDefinition<>(FIELD_1, MyDAO::setField1);

3)最後に、私は次のタイプセーフ作成したいaddField方法を:

private <T> void addField(FieldDefinition<T> fieldDefinition, String key, T value) {
    // ...
    fieldDefinition.getSetter().accept(this, value);
    // ...
}

これは、そのように呼ばれることwhould:

myDao.addField(FIELD_1_DEF, key, value);

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=207320&siteId=1