проблема дженериков Java - PullRequest
       1

проблема дженериков Java

4 голосов
/ 16 февраля 2011

я новичок в концепции дженериков в 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;
}

выше код im с использованием метода parseFrom, но проблема в том, что этот метод будет существовать только в конкретных классах, т. е. какие классы расширяют класс Message, поэтому я не могу получить доступ к методу parseFrom с помощью этих обобщений.Как я могу решить это?

Спасибо, R.Ramesh

Ответы [ 6 ]

3 голосов
/ 16 февраля 2011

Передайте конструктору (-ам) объект фабрики по следующим строкам:

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

Если GPBFormat делает немного больше, чем вы указали, тогда, возможно, он должен быть абстрактнымделегировать на отдельную фабрику.

2 голосов
/ 16 февраля 2011

Это буферы протокола? Ваш parseFrom метод статичен?

Если parseFrom не является статичным, вы должны сделать

@Override
public boolean deSerialize(T message, byte[] value) 
{
    // protocol messages return boolean whether parsing succeeded
    return message.newBuilderForType().mergeFrom(value).build();
}
2 голосов
/ 16 февраля 2011

Вы можете объявить абстрактный parseFrom метод в вашем Message классе.Затем для его реализации потребуются конкретные классы, и это именно то, что вам нужно для корректной работы приведенного выше кода.

На основании комментария Тома Хоутина вот модифицированная версия моего ответа:

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 голос
/ 16 февраля 2011

Часто недостаточно просто передать переменную типа (T), но также и класс;например, десериализация обычно должна выглядеть примерно так:

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

, поскольку T в этом случае в основном используется компилятором для генерации неявных приведений.Таким образом, вам все еще нужен фактический класс для передачи - это одна из распространенных идиом Java, необходимая из-за стирания типа.

0 голосов
/ 05 сентября 2017

вам нужен универсальный парсер:

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

код клиента:

ConcreteMessage msg = deSerialize(byteArray, ConcreteMessage.getParserForType());
0 голосов
/ 16 февраля 2011

Вы можете получить доступ к методу parseFrom () таким образом, только если он статический.Если вы сделаете этот метод статическим, тогда этот код будет работать.Если вы не хотите делать это статическим, используйте для его вызова экземпляр, то есть метод экземпляра, который можно вызвать только через экземпляр.

...