java generics issue
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());
精彩评论