在Play 2.0中使用泛型的自定义格式化程序

时间:2012-07-06 21:14:55

标签: java generics data-binding formatting playframework-2.0

我想register自定义格式化程序来处理Set<Integer>

显而易见的方式:

Formatters.register(Set<Integer>.class, new AnnotationIntegerSetFormatter());

导致“非法表达”。什么是正确的方法,或者不可能?

2 个答案:

答案 0 :(得分:3)

Set<Integer>.class不是合法的Java,因为该类型的通用组件在编译时被擦除。我认为使用Set.class应该可行,但这会为所有Set<T>类型注册您的处理程序。

答案 1 :(得分:2)

使用Formatters.register(Set.class, new AnnotationIntegerSetFormatter());结束; parse仍然可以返回Set<Integer>,而print只需将Set投放到Set<Integer>

public class AnnotationIntegerSetFormatter extends Formatters.AnnotationFormatter<IntegerSet,Set> {
    @Override
    public Set<Integer> parse(IntegerSet annotation, String text, Locale locale) {
        Set<Integer> set = new TreeSet<Integer>();
        for (String part : text.split(","))
            set.add(Integer.parseInt(part));

        return set;
    }

    @Override
    public String print(IntegerSet annotation, Set value, Locale locale) {
        List<Integer> sorted = new ArrayList<Integer>();
        sorted.addAll((Set<Integer>) value);
        Collections.sort(sorted);

        return join(",", sorted.toArray());
    }

    private static String join(String separator, Object... values) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < values.length; i++) {
            if (values[i] == null)
                continue;

            if (sb.length() > 0)
                sb.append(separator);

            sb.append(values[i].toString());
        }

        return sb.toString();
    }

}

并且为了完整性,我使用了注释:

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface IntegerSet {
    int min() default Integer.MIN_VALUE;
    int max() default Integer.MAX_VALUE;
}

由于这是基于注释的,因此您可以为Collection类型注册多个格式化程序,并通过注释区分它们。