Javaジェネリック変数<T>値

Java generics variable <T> value


質問 written by Sotirios Delimanolis @2016-08-17 18:18:08Z

: 6 : 3 : 700

現時点では、次のコードを使用してjpaでフィルタリングを実行しています。

if (value.getClass() == Integer.class) {
   return cb.greaterThan(root.<Integer>get(field), (Integer) value);
} else if (value.getClass() == Long.class) {
   return cb.greaterThan(root.<Long>get(field), (Long) value);
} else if (value.getClass() == Float.class) {
   return cb.greaterThan(root.<Float>get(field), (Float) value);
} else if (value.getClass() == Date.class) {
   return cb.greaterThan(root.<Date>get(field), (Date) value);
}

このブロックをそのような1行に減らすにはどうすればよいですか?

return cb.greaterThan(root.<value.getClass()>get(field), value);

したがって、<T>のT値をクラスタイプに置き換える必要があります。 悲しいことに、私はjavaジェネリックがそれほど得意ではありません。 誰もがアイデアを持っていますか? それも可能ですか?

ルートのタイプは次のとおりです。http//docs.oracle.com/javaee/6/api/javax/persistence/criteria/Path.html#get%28java.lang.String%29

編集:ここに私が書きたい完全なクラスがあります:

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

public class FilterExpression {

    public static final Integer BEGINS_WITH = 0;
    public static final Integer ENDS_WITH = 1;
    public static final Integer CONTAINS = 2;
    public static final Integer EQUAL = 3;
    public static final Integer NOT_EQUAL = 4;
    public static final Integer GREATER_THAN = 5;
    public static final Integer GREATER_EQUAL_THAN = 6;
    public static final Integer LESS_THAN = 7;
    public static final Integer LESS_EQUAL_THAN = 8;
    private static final Map<String, Integer> OPERATOR_MAPPING;

    static {
        Map<String, Integer> temp = new HashMap<>();
        temp.put("bw", BEGINS_WITH);
        temp.put("ew", ENDS_WITH);
        temp.put("ct", CONTAINS);
        temp.put("eq", EQUAL);
        temp.put("nq", NOT_EQUAL);
        temp.put("gt", GREATER_THAN);
        temp.put("gq", GREATER_EQUAL_THAN);
        temp.put("lt", LESS_THAN);
        temp.put("lq", LESS_EQUAL_THAN);
        OPERATOR_MAPPING = Collections.unmodifiableMap(temp);
    }

    private String field;
    private Integer operator;
    private Object value;

    public FilterExpression(String field, String operator, String value, Class c) {
        this.field = field;
        setOperator(operator);
        setValue(value, c);
    }

    public Boolean validate() {
        if (StringUtils.isEmpty(field) || operator == null || value == null) {
            return false;
        }
        Class c = value.getClass();

        if (c == String.class) {
            return operator >= BEGINS_WITH && operator <= NOT_EQUAL;
        } else if (c == Integer.class || c == Float.class || c == Double.class) {
            return (EQUAL >= EQUAL && operator <= LESS_EQUAL_THAN);
        } else if (c == Boolean.class) {
            return operator == EQUAL || operator == NOT_EQUAL;
        } else if (c == Identification.Type.class) {
            return operator == EQUAL || operator == NOT_EQUAL;
        }
        return false;
    }

    public String getField() {
        return field;
    }

    public void setField(String field) {
        this.field = field;
    }

    public Integer getOperator() {
        return operator;
    }

    public void setOperator(String operator) {
        this.operator = OPERATOR_MAPPING.get(operator.toLowerCase());
    }

    public Object getValue() {
        return value;
    }

    public void setValue(String s, Class c) {
        try {
            if (Boolean.class == c) {
                this.value = validateBoolean(s);
            } else if (Integer.class == c) {
                this.value = Integer.parseInt(s);
            } else if (Float.class == c) {
                this.value = Float.parseFloat(s);
            } else if (Identification.Type.class == c) {
                this.value = Identification.Type.parse(Integer.parseInt(s));
            } else {
                this.value = s;
            }
        } catch (NumberFormatException ex) {
            this.value = null;
        }
    }

    public <R> Predicate toPredicate(CriteriaBuilder cb, Root<R> root) {
        if (Objects.equals(operator, FilterExpression.EQUAL)) {
            return cb.equal(root.get(field), value);
        } else if (Objects.equals(operator, FilterExpression.NOT_EQUAL)) {
            return cb.notEqual(root.get(field), value);
        } else if (Objects.equals(operator, FilterExpression.CONTAINS)) {
            return cb.like(root.<String>get(field), "%" + value + "%");
        } else if (Objects.equals(operator, FilterExpression.ENDS_WITH)) {
            return cb.like(root.<String>get(field), "%" + value);
        } else if (Objects.equals(operator, FilterExpression.BEGINS_WITH)) {
            return cb.like(root.<String>get(field), value + "%");
        } else if (Objects.equals(operator, FilterExpression.GREATER_THAN)) {
            if (value.getClass() == Integer.class) {
                return cb.greaterThan(root.<Integer>get(field), (Integer) value);
            } else if (value.getClass() == Float.class) {
                return cb.greaterThan(root.<Float>get(field), (Float) value);
            } else if (value.getClass() == Date.class) {
                return cb.greaterThan(root.<Date>get(field), (Date) value);
            }
        } else if (Objects.equals(operator, FilterExpression.GREATER_EQUAL_THAN)) {
            if (value.getClass() == Integer.class) {
                return cb.greaterThanOrEqualTo(root.<Integer>get(field), (Integer) value);
            } else if (value.getClass() == Float.class) {
                return cb.greaterThanOrEqualTo(root.<Float>get(field), (Float) value);
            } else if (value.getClass() == Date.class) {
                return cb.greaterThanOrEqualTo(root.<Date>get(field), (Date) value);
            }
        } else if (Objects.equals(operator, FilterExpression.LESS_THAN)) {
            if (value.getClass() == Integer.class) {
                return cb.lessThan(root.<Integer>get(field), (Integer) value);
            } else if (value.getClass() == Float.class) {
                return cb.lessThan(root.<Float>get(field), (Float) value);
            } else if (value.getClass() == Date.class) {
                return cb.lessThan(root.<Date>get(field), (Date) value);
            }
        } else if (Objects.equals(operator, FilterExpression.LESS_EQUAL_THAN)) {
            if (value.getClass() == Integer.class) {
                return cb.lessThanOrEqualTo(root.<Integer>get(field), (Integer) value);
            } else if (value.getClass() == Float.class) {
                return cb.lessThanOrEqualTo(root.<Float>get(field), (Float) value);
            } else if (value.getClass() == Date.class) {
                return cb.lessThanOrEqualTo(root.<Date>get(field), (Date) value);
            }
        }
        return null;
    }
コメント 1

rootとはどのタイプですか?get()メソッドはどのように定義されていますか?cbとは?

written by RealSkeptic @2016-08-17 14:59:56Z

コメント 2

それを質問に追加しました

written by ペロトム @2016-08-17 15:01:33Z

コメント 3

root.<Integer>get(field)の結果はroot.<Integer>get(field) root.<Long>get(field)と同じであることに注意してくださいroot.<Integer>get(field)このタイプは実行時に利用できないためです。メソッドから返される唯一の有効な安全な値はnullです。

written by アンディターナー @2016-08-17 15:01:34Z

コメント 4

cb.greaterThan(root.get(field),(Comparable<?>)value)を試しcb.greaterThan(root.get(field),(Comparable<?>)value)か?

written by RealSkeptic @2016-08-17 15:14:03Z

コメント 5

EQUAL >= EQUAL平等は難しい目標です

written by -Joop Eggen @2016-08-17 15:17:46Z

回答 1 written by コード @2016-08-17 15:13:51Z
3

クラス全体をジェネリックにすることができると思います。

public class FilterExpression<T extends Comparable<T>> {
    //Make value to be type T instead of Object.
    T value;

    // And you could easily do,
    ...
    return cb.greaterThan(root.<T>get(field), value);
}
コメント 1

私もそれについて考えましたが、setValueメソッドでジェネリッククラスのタイプをどのように設定しますか?

written by ペロトム @2016-08-17 15:16:52Z

コメント 2

これは何が起こる必要があるかの始まりです...異なるクラスのロジックがすべてこのクラスで生きる必要がある理由には、いくつかのロジスティクスの問題があります。

written by 誠 @2016-08-17 15:17:40Z

コメント 3

わかりましたが、この汎用クラスを変数型でどのように構築できますか?たとえば、現在、Map <String、Class>からタイプを判別しています。

written by ペロトム @2016-08-17 15:20:35Z

コメント 4

@ user2630406ジェネリック型からクラスを決定することはできません。クラスをパラメーターとして必要なメソッドに渡す必要があります。この投稿を参照しください

written by チャールズフォレット @2016-08-17 15:23:43Z

回答 2 written by ニコラス・フィロット @2016-08-17 15:40:55Z
2

すべてが混在しているため、メソッドのコードは複雑であるため、メソッドをリファクタリングするつもりがない場合、最も単純なソリューションは次のように生のタイプに依存しています:

return cb.greaterThan(root.<Comparable>get(field), (Comparable) value);
コメント 1

ええ生のタイプ。

written by RealSkeptic @2016-08-17 15:30:36Z

コメント 2

@RealSkepticそれは理想的な解決策ではないことに同意しますが、すべてが混在しているOPのメソッドのコードに関しては、彼がコードをリファクタリングしない限り、はるかに簡単です。最も簡単なソリューションがある場合は、共有してください

written by ニコラスフィロット @2016-08-17 15:34:02Z

回答 3 written by @2016-08-17 15:44:23Z
0

codebenderとnicolas filottoからの2つの回答により、私はそれを行うことができました。 クラスの外に置くためにsetValueメソッドを削除する必要がありました。 これが完全なクラスです:

public class FilterExpression<T extends Comparable<T>> {

    public static final Integer BEGINS_WITH = 0;
    public static final Integer ENDS_WITH = 1;
    public static final Integer CONTAINS = 2;
    public static final Integer EQUAL = 3;
    public static final Integer NOT_EQUAL = 4;
    public static final Integer GREATER_THAN = 5;
    public static final Integer GREATER_EQUAL_THAN = 6;
    public static final Integer LESS_THAN = 7;
    public static final Integer LESS_EQUAL_THAN = 8;
    private static final Map<String, Integer> OPERATOR_MAPPING;

    static {
        Map<String, Integer> temp = new HashMap<>();
        temp.put("bw", BEGINS_WITH);
        temp.put("ew", ENDS_WITH);
        temp.put("ct", CONTAINS);
        temp.put("eq", EQUAL);
        temp.put("nq", NOT_EQUAL);
        temp.put("gt", GREATER_THAN);
        temp.put("gq", GREATER_EQUAL_THAN);
        temp.put("lt", LESS_THAN);
        temp.put("lq", LESS_EQUAL_THAN);
        OPERATOR_MAPPING = Collections.unmodifiableMap(temp);
    }

    private String field;
    private Integer operator;
    private T value;

    public FilterExpression(String field, String operator, T value) {
        this.field = field;
        setOperator(operator);
        this.value = value;
    }

    public Boolean validate() {
        if (StringUtils.isEmpty(field) || operator == null || value == null) {
            return false;
        }
        Class c = value.getClass();

        if (c == String.class) {
            return operator >= BEGINS_WITH && operator <= NOT_EQUAL;
        } else if (c == Integer.class || c == Float.class || c == Double.class || c == Date.class) {
            return (EQUAL >= EQUAL && operator <= LESS_EQUAL_THAN);
        } else if (c == Boolean.class) {
            return operator == EQUAL || operator == NOT_EQUAL;
        } else if (c == Identification.Type.class) {
            return operator == EQUAL || operator == NOT_EQUAL;
        }
        return false;
    }

    public String getField() {
        return field;
    }

    public void setField(String field) {
        this.field = field;
    }

    public Integer getOperator() {
        return operator;
    }

    public void setOperator(String operator) {
        this.operator = OPERATOR_MAPPING.get(operator.toLowerCase());
    }

    public T getValue() {
        return value;
    }

    public void setValue(T value) {
        this.value = value;
    }

    public <R> Predicate toPredicate(CriteriaBuilder cb, Root<R> root) {
        if (Objects.equals(operator, FilterExpression.EQUAL)) {
            return cb.equal(root.<T>get(field), value);
        } else if (Objects.equals(operator, FilterExpression.NOT_EQUAL)) {
            return cb.notEqual(root.<T>get(field), value);
        } else if (Objects.equals(operator, FilterExpression.CONTAINS)) {
            return cb.like(root.<String>get(field), "%" + value + "%");
        } else if (Objects.equals(operator, FilterExpression.ENDS_WITH)) {
            return cb.like(root.<String>get(field), "%" + value);
        } else if (Objects.equals(operator, FilterExpression.BEGINS_WITH)) {
            return cb.like(root.<String>get(field), value + "%");
        } else if (Objects.equals(operator, FilterExpression.GREATER_THAN)) {
            return cb.greaterThan(root.<T>get(field), (T) value);
        } else if (Objects.equals(operator, FilterExpression.GREATER_EQUAL_THAN)) {
            return cb.greaterThanOrEqualTo(root.<T>get(field), (T) value);
        } else if (Objects.equals(operator, FilterExpression.LESS_THAN)) {
            return cb.lessThan(root.<T>get(field), (T) value);
        } else if (Objects.equals(operator, FilterExpression.LESS_EQUAL_THAN)) {
            return cb.lessThanOrEqualTo(root.<T>get(field), (T) value);
        } 
        return null;
    }

}