You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java泛型重写静态方法的变通方案及自定义序列化问询

Got it, let's work through building a flexible, multi-implementation serialization system for your generic objects—since Java's built-in serialization is notoriously rigid, insecure, and prone to versioning issues, rolling your own modular setup is a smart move. Here's how to structure it to support multiple custom serializers while keeping your generic Foo class clean and reusable:

1. Optimize the Abstract Serializer Base Class (Generic-Friendly)

First, tweak your abstract Serializer to properly handle generic types—since Java's type erasure hides generic info at runtime, we'll use a TypeReference (or a custom type token) to capture that context during deserialization:

public abstract class Serializer<T> {
    // Serialize an instance to raw bytes
    public abstract byte[] toBytes(T instance);
    
    // Deserialize bytes back to T, using TypeReference to preserve generic type info
    public abstract T fromBytes(byte[] data, TypeReference<T> typeRef);
}

Note: You can implement your own TypeReference or use the one from libraries like Jackson—either way, it lets you handle generic types like List<MyObject> that would otherwise be erased.

2. Implement Multiple Custom Serialization Strategies

Create concrete Serializer subclasses for each format you want to support. Here are common examples:

JSON Serializer (Using Jackson)

public class JsonSerializer<T> extends Serializer<T> {
    private final ObjectMapper mapper = new ObjectMapper();

    @Override
    public byte[] toBytes(T instance) {
        try {
            return mapper.writeValueAsBytes(instance);
        } catch (JsonProcessingException e) {
            throw new SerializationException("JSON serialization failed", e);
        }
    }

    @Override
    public T fromBytes(byte[] data, TypeReference<T> typeRef) {
        try {
            return mapper.readValue(data, typeRef);
        } catch (IOException e) {
            throw new SerializationException("JSON deserialization failed", e);
        }
    }
}

Protobuf Serializer

public class ProtobufSerializer<T extends Message> extends Serializer<T> {
    private final Parser<T> parser;

    public ProtobufSerializer(Parser<T> parser) {
        this.parser = parser;
    }

    @Override
    public byte[] toBytes(T instance) {
        return instance.toByteArray();
    }

    @Override
    public T fromBytes(byte[] data, TypeReference<T> typeRef) {
        try {
            return parser.parseFrom(data);
        } catch (InvalidProtocolBufferException e) {
            throw new SerializationException("Protobuf deserialization failed", e);
        }
    }
}

Custom Binary Serializer (Your Own Format)

public class CustomBinarySerializer<T extends User> extends Serializer<T> {
    @Override
    public byte[] toBytes(T instance) {
        // Implement your own compact binary logic
        try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
             DataOutputStream dos = new DataOutputStream(baos)) {
            dos.writeUTF(instance.getUsername());
            dos.writeInt(instance.getAge());
            return baos.toByteArray();
        } catch (IOException e) {
            throw new SerializationException("Custom binary serialization failed", e);
        }
    }

    @Override
    public T fromBytes(byte[] data, TypeReference<T> typeRef) {
        try (ByteArrayInputStream bais = new ByteArrayInputStream(data);
             DataInputStream dis = new DataInputStream(bais)) {
            String username = dis.readUTF();
            int age = dis.readInt();
            return (T) new User(username, age);
        } catch (IOException e) {
            throw new SerializationException("Custom binary deserialization failed", e);
        }
    }
}
3. Make Generic Class Foo Work With Any Serializer

Update Foo to accept a Serializer instance via constructor or setter—this lets you swap implementations without modifying Foo itself:

public class Foo<T> {
    private final Serializer<T> serializer;

    // Inject serializer via constructor for dependency injection compatibility
    public Foo(Serializer<T> serializer) {
        this.serializer = serializer;
    }

    public byte[] serialize(T obj) {
        return serializer.toBytes(obj);
    }

    public T deserialize(byte[] data, TypeReference<T> typeRef) {
        return serializer.fromBytes(data, typeRef);
    }
}
4. Optional: Add a Factory to Manage Serializers

To avoid creating Serializer instances everywhere, use a factory to fetch the right implementation based on format:

public class SerializerFactory {
    public enum Format { JSON, PROTOBUF, CUSTOM_BINARY }

    public static <T> Serializer<T> getSerializer(Format format) {
        return switch (format) {
            case JSON -> new JsonSerializer<>();
            case CUSTOM_BINARY -> new CustomBinarySerializer<>();
            case PROTOBUF -> throw new IllegalArgumentException("Protobuf requires a parser—use overloaded method");
        };
    }

    // Overloaded method for Protobuf (needs a specific parser)
    public static <T extends Message> Serializer<T> getProtobufSerializer(Parser<T> parser) {
        return new ProtobufSerializer<>(parser);
    }
}

Usage Example

// Use JSON serializer
Foo<User> jsonFoo = new Foo<>(SerializerFactory.getSerializer(SerializerFactory.Format.JSON));
byte[] userBytes = jsonFoo.serialize(new User("Alice", 30));
User deserialized = jsonFoo.deserialize(userBytes, new TypeReference<User>() {});

// Use Protobuf serializer
Parser<UserProto> protoParser = UserProto.parser();
Foo<UserProto> protoFoo = new Foo<>(SerializerFactory.getProtobufSerializer(protoParser));
Key Advantages of This Setup
  • Flexibility: Swap serializers (JSON → Protobuf → custom binary) without touching domain code.
  • Type Safety: Generics ensure you're always working with the correct object type.
  • Maintainability: Each serializer handles one format, keeping code modular and testable.
  • Avoids Java Serialization Flaws: No more serialVersionUID headaches, tight class coupling, or security vulnerabilities.

内容的提问来源于stack exchange,提问作者MeetTitan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 04:18:00