【问题标题】:GWT Serialize Ordering/Comparator of TreeMapGWT 序列化 TreeMap 的排序/比较器
【发布时间】:2012-04-24 20:03:58
【问题描述】:

我有一个带有 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();

【问题讨论】:

  • 根据文档CASE_INSENSITIVE_ORDER is 可序列化:一个比较器,它通过 compareToIgnoreCase 对字符串对象进行排序。这个比较器是可序列化的。 那么你会得到什么错误呢?
  • 其实并非如此。 (@查看编辑)
  • 看起来@eneveu 的回答可能会有所帮助。

标签: java serialization gwt guava treemap


【解决方案1】:

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

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

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

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

【讨论】:

  • 这是正确的提示。在将比较器实现为嵌套类之后。我需要使它成为非私有的。所以你的 3 并不是真的必要。
  • 3 是必要的,以确保反序列化的订单与原始订单相同。如果您可以使用多个 MyOrdering 实例,则可以跳过它。
【解决方案2】:

错误的堆栈跟踪会很有帮助。但我会冒险猜测您会遇到如下异常:

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;
}

【讨论】:

    猜你喜欢
    • 2022-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-21
    • 1970-01-01
    相关资源
    最近更新 更多