有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

Java泛型覆盖静态方法解决方案

我正在做一个需要序列化和反序列化通用对象的项目。我要做的是定义一个抽象类Serializer,它实现了toBytes()和静态fromBytes()。这种方法一切都很好,因为我可以将对象实例传递给需要Foo子类的泛型类Serializer,并且我可以确保对象知道如何序列化和反序列化自己

现在我的问题。Java序列化有点糟糕。我有多个实现,我想尝试交换,最终我希望用户能够决定格式。我将如何更改Serializer的实现细节?我知道我不能重写静态方法,所以如果不解耦FooSerializer,并且不能确保我的泛型对象在Foo中有适当的toBytes()fromBytes()方法,我怎么做呢

如果有人感到困惑,下面是代码:

public abstract class Serializer {
    public static Serializer fromBytes(byte[] bytes) {
        ...
    }

    public byte[] toBytes() {
        ...
    }
}

public class Foo<T extends Serializer> {
    private T t;
    public Foo(T t) {
        this.t = t;
    }

    public void foo() {
        t.toBytes(); //this will polymorph into the correct call because it's called on the object instance and not the Serializer class
    }

    public void bar(byte[] bytes) {
        T.fromBytes(bytes); // I'd like to be able to override this method so I can use different implementations
    }
}

共 (1) 个答案

  1. # 1 楼答案

    我不确定这是否是一种好方法,但使用Jackson库并将对象序列化为json节点怎么样?例如:

    @JsonTypeInfo(
              use = JsonTypeInfo.Id.NAME, 
              include = JsonTypeInfo.As.PROPERTY, 
              property = "type")
            @JsonSubTypes({ 
              @Type(value = SoundFile.class, name = "sound"), 
              @Type(value = VideoFile.class, name = "video") 
            })
    abstract class File{
        private String id;
        private String type;
        @JsonCreator
        public File(@JsonProperty("id") String id)
        {
            this.id=id;
        }
        public String getId() {return this.id;}
        public abstract String getType();
    }
    
    class SoundFile extends File{
    
        @JsonCreator
        public SoundFile(@JsonProperty("id") String id) {
            super(id);
        }
    
        @Override
        public String getType() {
            return "sound";
        }
    
    
    }
    
    class VideoFile extends File{
    
        @JsonCreator
        public VideoFile(@JsonProperty("id") String id) {
            super(id);
        }
    
        @Override
        public String getType() {
            return "video";
        }
    
    }
    
    public class GenericApp {
    
    
    
        public static void main(String[] args) {
        ObjectMapper om = new ObjectMapper();
    
        List<File> files = Arrays.asList(new VideoFile("1"),new SoundFile("2"));
    
        //serialize
        List<byte[]> fileSerialized = files.stream().map(file->{
            try {
            return om.writeValueAsBytes(file);
            }catch(Exception e) {return null;}
        }).collect(Collectors.toList());
    
        //de-serialize
        List<File> filesDeSerialized = fileSerialized.stream().map(bytes ->{
            try {
                return om.readValue(bytes, File.class);
            }
            catch(Exception e) {return null;}
        }).collect(Collectors.toList());
    
        filesDeSerialized.stream().forEach(file->{
            System.out.println("id :"+file.getId()+" - "+file.getClass());
        });
    
        }
    
    }
    

    这将正确地反序列化这些对象并打印:

    id :1 - class com.dsncode.stackoverflow.VideoFile
    id :2 - class com.dsncode.stackoverflow.SoundFile
    

    但是,应该为泛型类型的所有子类定义@JsonTypeInfo和@JsonSubType。因为,通过指示此字段,您将向Jackson反序列化器指示应该为泛型类型创建哪个类