Невозможно сериализовать общий класс с общим полем в Kryo

У меня возникла странная проблема с Kryo. Я могу сериализовать универсальный класс (например, List) просто отлично. Я даже могу сериализовать универсальный класс, у которого нет общих полей. Однако, если я сериализую универсальный класс с универсальными полями, он выйдет из строя. Пример должен показать проблему.

Вот класс, который я хочу сериализовать:

import java.util.ArrayList;

public class GenericClass<T>
{
    private final ArrayList<T> list;

    public GenericClass()
    {
        list = new ArrayList<T>();
    }
}

И вот код, который это проверяет. Второй вызов writeClassAndObject() вызывает исключение. Запись ArrayList просто доказывает, что работает нормально.

public void testWhySoDumb()
{
    File s = Environment.getExternalStorageDirectory();
    String dir = s.getAbsolutePath() + "/pagetest";
    String fileLocation = dir + "/filetest";
    new File(dir).mkdirs();
    Output output = null;

    Kryo kryo = new Kryo();
    kryo.setAsmEnabled(true);
    kryo.setDefaultSerializer(CompatibleFieldSerializer.class);

    // Test writing ArrayList (this works)
    List<Integer> arrayList = new ArrayList<Integer>();

    try
    {
        output = new Output(new FileOutputStream(fileLocation));
        kryo.writeClassAndObject(output, arrayList);
    }
    catch (Exception e)
    {
        System.out.println(e.getMessage()); // No problem here
    }
    finally
    {
        if (output != null)
        {
            output.close();
        }
    }

    // Test writing GenericClass (this does NOT work)
    GenericClass<Integer> genericClass = new GenericClass<Integer>();

    try
    {
        output = new Output(new FileOutputStream(fileLocation));
        kryo.writeClassAndObject(output, genericClass); // throws exception!!! <------
    }
    catch (Exception e)
    {
        System.out.println(e.getMessage()); 
    }
    finally
    {
        if (output != null)
        {
            output.close();
        }
    }
}

И я получаю следующее исключение:

com.esotericsoftware.kryo.KryoException: java.lang.IllegalArgumentException: type cannot be null.
Serialization trace:
list (com.myapp.page.history.GenericClass)
at com.esotericsoftware.kryo.serializers.ObjectField.write(ObjectField.java:82)
at com.esotericsoftware.kryo.serializers.CompatibleFieldSerializer.write(CompatibleFieldSerializer.java:42)
at com.esotericsoftware.kryo.Kryo.writeClassAndObject(Kryo.java:624)
at com.myapp.page.history.TestGenerics.testWhySoDumb(TestGenerics.java:57)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:191)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:176)
at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:555)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1837)
Caused by: java.lang.IllegalArgumentException: type cannot be null.
at com.esotericsoftware.kryo.Kryo.isFinal(Kryo.java:1135)
at com.esotericsoftware.kryo.serializers.CollectionSerializer.setGenerics(CollectionSerializer.java:60)
at com.esotericsoftware.kryo.serializers.ObjectField.write(ObjectField.java:60)
... 15 more

Что очень странно, так это то, что если я изменю тип «списка» с «ArrayList» на просто «T», он будет работать нормально. Kryo, похоже, не знает, что делать с полем ArrayList. Я использую Kryo версии 3.0.0.

Спасибо!


person Mark Herscher    schedule 12.01.2015    source источник


Ответы (1)


Я не знаю, есть ли у вас все еще эта проблема. Я, вероятно, подумал бы, что это проблема версии или что-то особенное для Android, потому что это должно работать с текущей версией.

Kryo kryo = new Kryo();
Output output = new Output(new FileOutputStream("fileLocation"));
kryo.writeObject(output, new GenericClass<String>());
person jeremie    schedule 22.07.2015