java - 如何使用接口(interface)实例属性序列化类?得到 NotSerializableException

标签 java android serialization interface

我有一个类:

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;
    }
}

还有一个接口(interface):

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

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

更新:

这是完整的代码,以使其更清晰:

(我从 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();
    }

}
}

最佳答案

当您将类定义为 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 类或单独的公共(public) java 类。

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

正如我所说,制作可序列化的全新类是很困难的。 但是,您可以提取所有可能实现之间的所有通用代码,并且只传递可能会发生变化的变量。这样,您将保持 Serializable 特性,并可能实现您的目标。

关于java - 如何使用接口(interface)实例属性序列化类?得到 NotSerializableException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35831117/

相关文章:

java - 自定义MonetaryAmount JSR354/mo​​neta的Databind Json序列化格式

java - 日志消息中美元符号 ($) 的含义

android - 如何获取我点击的列表项数据?

json - 如何在 Dart 中使用带有 json 序列化的泛型和泛型列表?

java - 跨 Kafka 分区对消息进行排序并将其放入另一个 Kafka 主题中

java - 如何在 IntelliJ 中的 Java Swing (JGoodies) 中使用 FormLayout

java - Activity 巴士回顾

java - 在 JavaFX 中使用新按钮动态更新 GridPane -> 如何重绘?

java - 搜索 View 在 Android 工具栏中无法正常工作

c# - JSON : what is the java Map equivalent in c#