GWT序列化TreeMap的排序/比较器

时间:2012-04-12 13:06:38

标签: java serialization gwt guava treemap

我有一个带有TreeMap的可序列化对象。

Map<String, Dogs> dogsByNames = Maps.newTreeMap(); // guava style

到目前为止,一切都很好。 现在忽略密钥的情况是必要的:

Map<String, Dogs> dogsByNames = Maps.newTreeMap(String.CASE_INSENSITIVE_ORDER);

这不起作用,因为String.CASE_INSENSITIVE_ORDER不是serialzable:

  

com.google.gwt.user.client.rpc.SerializationException:输入   'java.lang.String $ CaseInsensitiveComparator'未包括在内   可以通过此SerializationPolicy序列化的类型集   无法加载其Class对象。出于安全考虑,此类型   不会被序列化:instance =   java.lang.String$CaseInsensitiveComparator@f26f68

所以我创建了自己的一个:

private static abstract class MyComparator<T>
    implements
        Comparator<T>, // extends Ordering<T> do not work
        IsSerializable { // Serializable do not work
}

public static final MyComparator<String> CASE_INSENSITIVE_ORDER = new MyComparator<String>() {
    @Override
    public int compare(final String left, final String right) {
        if (null == left) {
            return (null == right) ? 0 : -1;
        } else if (null == right) {
            return 1;
        }
        return left.compareToIgnoreCase(right);
    }
};

但这仍然无效。

怎么了?

解决方案:

protected static class MyOrdering // no-private!!!
    extends
        Ordering<String>
    implements
        IsSerializable {
    @Override
    public int compare(final String left, final String right) {
        if (null == left) {
            return (null == right) ? 0 : -1;
        } else if (null == right) {
            return 1;
        }
        return left.compareToIgnoreCase(right);
    }
}

public static final Ordering<String> CASE_INSENSITIVE_ORDER = new MyOrdering();

2 个答案:

答案 0 :(得分:5)

您创建的CASE_INSENSITIVE_ORDER是一个匿名类,无法在GWT中序列化。要使GWT可序列化,您需要

  1. 创建自定义顶级课程(例如

    CaseInsensitiveOrder implements Comparator<..>, Serializable {
        ...
    }
    
  2. 像你一样创建一个常量CASE_INSENSITIVE_ORDER

  3. 为该类(CaseInsensitiveOrder_CustomFieldSerializer)创建自定义字段序列化程序,该字段序列化程序返回CASE_INSENSITIVE_ORDER上的deserialize()实例。

答案 1 :(得分:0)

错误的堆栈跟踪会有所帮助。但是我会冒这样的猜测,你会得到一个例外:

  

com.google.gwt.user.client.rpc.SerializationException:输入   'com.foo.Bar.MyComparator'未包括在可以的类型集中   由此SerializationPolicy序列化或其Class对象不能   加载。出于安全考虑,此类型不会被序列化

这是因为GWT在编译时创建了它可能需要序列化的所有类型的列表。这是“序列化政策”。为此,GWT检查所有RPC方法的参数和返回类型,并搜索所有“可到达”类型。

编译器可能没有意识到您的Comparator将被序列化,并且它没有被添加到序列化策略中。

解决方法是声明一个虚方法,该方法将所有可能需要序列化的类型作为参数,如this other SO answer中所述。类似的东西:

// in your RPC interface
SerializationWhitelist dummyMethodForSerializationPolicy(SerializationWhitelist serializationWhiteList);

// the SerializableWhiteList class
public class SerializationWhitelist {
    public Bar.MyComparator<String> myComparator;
}