Java 泛型问题

4

我对Java中的泛型概念还不熟悉。

在我的应用程序中,我在一个类中使用了泛型,以下是我的示例代码:

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

在上面的代码中,我使用了parseFrom方法,但问题是这个方法只存在于具体类中,即继承Message类的类中,因此我无法通过这个泛型访问parseFrom方法。我该怎么解决?

谢谢, R.Ramesh


你能贴出parseFrom方法的定义吗? - Necronet
6个回答

3

将一个工厂对象传递给构造函数,示例代码如下:

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

如果GPBFormat只是做了你引用的这些事情,那么它可能应该是抽象的,而不是委托给一个单独的工厂。

2
你可以在你的Message类中声明一个抽象的parseFrom方法。具体的类将需要实现它,这正是上面的代码需要的。根据Tom Hawtin的评论,这是我答案的修改版本。
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;
        }
    }
}

每个具体类都需要一个无参构造函数。

1
我不这么认为。没有实例可以调用该方法。 - Tom Hawtin - tackline
哎呀,我没有注意到 OP 正试图对一个静态方法进行静态引用。 - Ted Hopp

2

这些是协议缓冲区吗?你的parseFrom方法是静态的吗?

如果parseFrom不是静态的,你应该做:

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

谢谢您的回复,但问题仍然存在。在协议缓冲区的"Message"类中没有"parseFrom"方法,只有具体的类才有该方法。 - Rams
啊,我明白了,我改变了我的答案。你能试试我所做的更改吗? - sjr
太棒了,您介意点击“接受”以便其他人可以找到这个答案吗? - sjr

1
通常仅传递类型变量(T)是不够的,还需要传递类;例如,反序列化通常应该像这样:
public T deSerialize(byte[] value, Class<T> type)

因为在这种情况下,T 大多只是由编译器用于生成隐式转换。因此,您仍然需要传递实际的类 -- 这是一种常见的 Java 习惯用法,由于类型擦除而需要。


0
你需要一个通用的解析器:
@Override
public T deSerialize(byte[] value, Parser<T> parser) 
{
    return parser.parseFrom(value);
}

客户端代码:

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

0
你只能访问 parseFrom() 方法,当它是静态的时候。如果你将该方法设为静态,那么这段代码就会起作用。如果你不想把它设为静态的,那么就使用实例来调用它,即只能通过实例方法来调用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接