开发者

java generics issue

开发者 https://www.devze.com 2023-02-11 05:49 出处:网络
im new to generics concept in java In my application im using generics in one class, following is the my sample code

im new to generics concept in java

In my application im using generics in one class, following is the my sample code

public class GPBFormat<T extends Message> implements IGPBFormat<T> {
@Override
public byte[] serialize(T t) 
{
    return 开发者_StackOverflow中文版t.toByteArray();
}
@Override
public T deSerialize(byte[] value) 
{
    T.parseFrom(value);
    return null;
}

im above code im using parseFrom method, but the problem is this method will exist only in concrete classes i.e which classes extends the Message class, so im unable to access parseFrom method with this generics. How can i solve this?

Thanks, R.Ramesh


Pass in to the constructor(s) a factory object, along the lines of:

interface Parser<T extends Message> {
    T parseFrom(byte[] value);
}

If GPBFormat does little more than you've quoted, then perhaps it should be abstract and not delegate to a separate factory.


Are these protocol buffers? Is your parseFrom method static?

If parseFrom is not static, you should do

@Override
public boolean deSerialize(T message, byte[] value) 
{
    // protocol messages return boolean whether parsing succeeded
    return message.newBuilderForType().mergeFrom(value).build();
}


You can declare an abstract parseFrom method in your Message class. Concrete classes will then be required to implement it, which is exactly what you need for the above code to work properly.

Based on the comment by Tom Hawtin, here's a modified version of my answer:

public class GPBFormat<T extends Message> implements IGPBFormat<T> {
    private Class<T> clazz;
    public GPBFormat(Class<T> clazz) {
        this.clazz = clazz;
    }
    @Override
    public byte[] serialize(T t) {
        return t.toByteArray();
    }
    @Override
    public T deSerialize(byte[] value)
    {
        try {
            T thing = clazz.newInstance();
            thing.parseFrom(value);
            return thing;
        } catch (Exception e) {
            // report error
            return null;
        }
    }
}

Each concrete class will need a no-arg constructor.


Often it is not enough to just pass type variable (T), but also Class; for example, deserialize usually should be something like:

public T deSerialize(byte[] value, Class<T> type)

because T in this case is mostly just used by compiler to generate implicit casts. So you still need actual class to be passed -- this is one common Java idiom, needed due to type erasure.


You can access the parseFrom() method in this way only if it is static. If you make that method static then this code will work. If you don't want to make that static then use instance to call it that is an instance method can be called only through an instance.


you need a generic Parser :

@Override
public T deSerialize(byte[] value, Parser<T> parser) 
{
    return parser.parseFrom(value);
}

client code :

ConcreteMessage msg = deSerialize(byteArray, ConcreteMessage.getParserForType());
0

精彩评论

暂无评论...
验证码 换一张
取 消