【问题标题】:How to serialize a Class with an Interface instance attribute? Got NotSerializableException如何序列化具有接口实例属性的类?得到 NotSerializableException
【发布时间】:2016-06-20 06:11:45
【问题描述】:

我有一堂课:

public class MyEntity implements Serializable {

    public MyInterface myInterface;

    public String name;
    public int    value;

    public MyEntity(String name, int value) {
        this.name = name;
        this.value = value;
    }
}

还有一个接口:

public interface MyInterface {
    void customFunction(int value);
}

这个结构的目的是为了实现MyClass的每个实例都可以有不同的customFunction(value)实现。

就像这样:

MyEntity myEntity = new MyEntity("My entity", 100);
    myEntity.myInterface = new MyInterface() {
        @Override
        public void customFunction(int value) {
            //This is my custom function.
            //This can be different for every instance of MyEntity class
        }
    };

但是,如果我想序列化 MyClass 的实例,我会得到 NotSerializableException

java.io.NotSerializableException: com.adamvarhegyi.duelsofcodrer.controller.MainActivity$1 在 java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1344) 在 java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1651) 在 java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1497) 在 java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1461) 在 java.io.ObjectOutputStream.writeFieldValues(ObjectOutputStream.java:959) 在 java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:360) 在 java.io.ObjectOutputStream.writeHierarchy(ObjectOutputStream.java:1054) 在 java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1384) 在 java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1651) 在 java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1497) 在 java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1461) 在 com.adamvarhegyi.duelsofcodrer.controller.MainActivity.onCreate(MainActivity.java:62) 在 android.app.Activity.performCreate(Activity.java:6251) 在 android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107) 在 android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369) 在 android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476) 在 android.app.ActivityThread.-wrap11(ActivityThread.java) 在 android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344) 在 android.os.Handler.dispatchMessage(Handler.java:102) 在 android.os.Looper.loop(Looper.java:148) 在 android.app.ActivityThread.main(ActivityThread.java:5417) 在 java.lang.reflect.Method.invoke(Native Method) 在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

所以我的问题是我怎样才能做到这一点?如何序列化具有接口实例属性的类实例?

更新:

为了更清楚,这是完整的代码:

(我从MyEntityMyInterface 制作了内部类以使其更加简化。)

package com.adamvarhegyi.duelsofcodrer.controller;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;

import com.adamvarhegyi.duelsofcodrer.R;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class MainActivity extends Activity {

public interface MyInterface extends Serializable {
    void customFunction(int value);
}

public class MyEntity implements Serializable {

    public MyInterface myInterface;

    public String name;
    public int    value;

    public MyEntity(String name, int value) {
        this.name = name;
        this.value = value;
    }
}

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);


    MyEntity myEntity = new MyEntity("My entity", 100);

    myEntity.myInterface = new MyInterface() {
        @Override
        public void customFunction(int value) {
            //This is my custom function.
            //This can be different for every instance of MyEntity class
        }
    };


    //Trying to serialize
    try {
        FileOutputStream fos = openFileOutput("myfile", Context.MODE_PRIVATE);
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(myEntity);
        oos.close();
        fos.close();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

}
}

【问题讨论】:

  • 你做对了吗?
  • @RafaelCardoso 不,您的建议我仍然有例外。可以试试这个方法是否有效?
  • @RafaelCardoso 我已经用完整的代码更新了这个问题。
  • 亚当,请阅读:stackoverflow.com/questions/7144912/…。序列化内部类存在问题。尝试将它们移动到单独的文件并返回结果;)
  • @RafaelCardoso 好吧,这些类在单独的包中,我只是将它们移到活动中以完整地发布代码。所以错误仍然存​​在。很遗憾。

标签: java android serialization interface


【解决方案1】:

当您将您的类定义为public class MyEntity implements Serializable 时,您基本上是在定义MyEntity 的所有属性都应该是可序列化的。但是,MyInterface 不是,因此属性public MyInterface myInterface 不能被序列化,你会得到NotSerializableException

要解决这个问题,您的界面应该是Serializable 的实例,因此应该对其进行扩展。

public interface MyInterface extends Serializable 
{
    void customFunction(int value);
}

这样,MyEntity 将具有可序列化的所有属性,并且不会抛出任何错误。需要注意的是,intfloat 等所有基本数据类型都可以序列化,Strings 也是如此。

编辑

经过大量思考、阅读和重新阅读代码,我发现了您的问题。当您执行以下操作时:

myEntity.myInterface = new MyInterface() {
    @Override
    public void customFunction(int value) {
        //This is my custom function.
        //This can be different for every instance of MyEntity class
    }
};

你实际上是在创建一个全新的 nameless 内部类,它实现了MyInterface。然而,由于这是一个内部类,它引用了它的父类Activity。 Activity 不是可序列化的,这就是它抛出 NotSerializableException 的原因。

如何解决?

您无法创建可序列化的自定义类。但是,有一条出路。

您可以在单独的文件中创建一个新类(例如,名为 CustomInterfaceImplementation )并创建它的实例,或者创建一个 Activity 的内部类 static(请注意,此 Activity 不会在您的 onCreate() 方法内创建,因为这没有任何意义。它应该在任何方法的范围之外和 Activity 范围内创建。

所以,例如,你可以有类似的东西:

CustomInterfaceImplementation customImpl = new CustomInterfaceImplementation();
myEntity.myInterface = customImpl;

上面的代码可以工作,CustomInterfaceImplementation 可以是 MainActivity 中的 static 类,也可以是单独的公共 java 类。

但是,如果我想制作随 obj 不同而变化的移动类怎么办?

正如我所说,要创建全新的 Serializable 类是很困难的。 但是,您可以提取所有可能的实现之间的所有公共代码,并且只传递可能会发生变化的变量。这样,您将保持Serializable 特征,并且可能能够实现您的目标。

【讨论】:

  • 如果我尝试简单地将“implements Serializable”写入我的接口,就像我的班级一样,我会收到错误消息。 “接口不允许实现子句”如何使接口可序列化?
  • @AdamVarhegyi 对不起,它应该是extends 而不是implements,因为接口继承自其他
  • 我还是有异常,请你试试这个方法看看是否真的有效?
  • @AdamVarhegyi 你能发布你的项目结构吗?比如,您的文件是如何处理的?
  • 是的,它正在工作。感谢您的努力,拉斐尔。
【解决方案2】:

要么使 MyInterface 可序列化,要么像这样向 myInterface 添加瞬态:

    public class MyEntity implements Serializable {
        public transient MyInterface myInterface;
        // ...
    }

使 myInterface 瞬态标记变量不被序列化。

【讨论】:

  • 我希望它被序列化。
  • 在这种情况下,你会写... public interface MyInterface extends Serializable
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-06-14
  • 2021-04-23
  • 1970-01-01
  • 1970-01-01
  • 2023-04-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多