4

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

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

到目前为止,一切都很好。现在可以忽略键的大小写:

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

这不起作用,因为 String.CASE_INSENSITIVE_ORDER 不可序列化:

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();
4

2 回答 2

5

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

  1. 创建一个自定义顶级类(如

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

  3. 为该类 ( CaseInsensitiveOrder_CustomFieldSerializer) 创建一个自定义字段序列化程序,它返回CASE_INSENSITIVE_ORDER实例 on deserialize()
于 2012-04-13T00:44:02.167 回答
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;
}
于 2012-04-12T22:08:16.310 回答