0

我用 序列化一个列表flexjson。序列化后,我打印对象hashcode()并检查对象是否相等。

问题,操作后对象引用发生了变化。我不想要它。

我的代码;

    String sameOfString="sameOfString";
    List<Object> list=new ArrayList<Object>();
    list.add(sameOfString);
    list.add(sameOfString);
    list.add("differentString");

    for(Object str:list){
        System.out.println(str.hashCode());
    }
    **System.out.println(list.get(0)==list.get(1));**
    System.out.println(list.get(0)==list.get(2));
    System.out.println("--");
    String json= new JSONSerializer().exclude("*.class").deepSerialize(list);
    List<String> listDeserilized = (List<String>) new JSONDeserializer().deserialize(json);
    for(Object str:listDeserilized){
        System.out.println(str.hashCode());
    }
    **System.out.println(listDeserilized.get(0)==listDeserilized.get(1));**
    System.out.println(listDeserilized.get(0)==listDeserilized.get(2));

和输出..

1018069468

1018069468

199675306

真的

错误的

-

1018069468

1018069468

199675306

错误的

错误的

如何解决这个问题?

4

3 回答 3

1

我用jackson lib解决了我的问题。

@JsonIdentityInfo注释保护对象关系(换句话说;保护引用)并且在反序列化之后,对象位置在内存中不会改变。

最终代码:

package com.maar.projectbuilder;

import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeName;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by Firat on 11.9.2014.
 */
public class Testt {
    @JsonDeserialize(as=StringClazz.class)
    @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="@class")
    @JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="@id")
    @JsonTypeName(value = "StringClazz")
    private static class StringClazz{
        private String data="";

        public StringClazz() {
        }

        public String getData() {
            return data;
        }

        public void setData(String data) {
            this.data = data;
        }
    }
    public static void main(String[] args) throws IOException {
        StringClazz someOfString=new StringClazz();
        someOfString.setData("someOfString");
        StringClazz differentString=new StringClazz();
        differentString.setData("differentString");

        List<StringClazz> list=new ArrayList<StringClazz>();
        list.add(someOfString);
        list.add(someOfString);
        list.add(differentString);

        for(Object str:list){
            System.out.println(str.hashCode());
        }
        System.out.println(list.get(0)==list.get(1));
        System.out.println(list.get(0)==list.get(2));
        System.out.println("-------");
        String json= null;
        try {
            json = new ObjectMapper().enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL).writeValueAsString(list);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        System.out.println(json);
        List<StringClazz> listDeserilized =new ObjectMapper().enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL).readValue(json, new TypeReference<List<StringClazz>>() {
        });
        for(Object str:listDeserilized){
            System.out.println(str.hashCode());
        }
        System.out.println(listDeserilized.get(0)==listDeserilized.get(1));
        System.out.println(listDeserilized.get(0)==listDeserilized.get(2));
    }
}
于 2014-09-12T09:19:01.543 回答
0

如何解决这个问题?

你没有。反序列化一个对象意味着在内存的不同位置创建一个新实例。

但是,我不建议这样做,您可以保留对象注册表(HashMap可能),执行反序列化,检查注册表是否包含对象,并将其替换为现有对象。

String课程已经为您提供了一些这种实习行为。见String#intern()

于 2014-09-11T14:30:24.870 回答
0

你所苦苦挣扎的是什么是平等?在 Java 中有两个版本的相等(与许多现代语言一样)。

  1. 这些对象的价值是否相等?
  2. 这些对象是同一个对象吗?(即通过参考)

这分别是 .equals() 和 == 之间的区别。当您反序列化某些内容时,它会创建一个新对象,因此如果您有另一个您序列化的对象副本。它永远不会是数字 2 相等(即通过引用相等)。因为反序列化被赋予了 JSON 表示,并从中创建了一个新的对象图。

但它可能是 .equals() ,前提是您的对象正确定义了 .equals() 对包含的所有对象的含义。默认情况下 Object.equals() 比较引用并且与 == 相同。但是,每个对象都可以重载它,并且在 String.equals() 的情况下比较字符串的实际内容。

因此,只需将您的代码更改为使用 .equals() 而不是 == ,您就会得到您所期望的:

System.out.println( list.get(0).equals( list.get(1) ) )
System.out.println( list.get(0).equals( list.get(2) ) )
于 2014-09-11T16:33:15.300 回答