Java – How do I serialize a class using the interface instance property? Get NotSerializableException

How do I serialize a class using the interface instance property? Get NotSerializableException… here is a solution to the problem.

How do I serialize a class using the interface instance property? Get NotSerializableException

I have a class:

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

There is also an interface:

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

The gist of this structure is that each instance that implements MyClass can have a different customFunction(value) implementation.

Like:

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

However, if I want to serialize an instance of MyClass, I get 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)

So my question is, how can I do this? How do I serialize an instance of a class with an interface instance attribute?

Update:

Here is the complete code to make it clearer:

(I created inner classes from MyEntity and MyInterface to make it more simplified.) )

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

}
}

Solution

When you define a class as public class MyEntity implements Serializable, you are essentially defining that all properties of MyEntity should be serializable. However, MyInterface is not, so the property public MyInterface myInterface cannot be serialized, and you get NotSerializableException.

To solve this problem, your interface should be an instance of Serializable, so it should extend it.

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

This way, MyEntity will have all the properties that can be serialized and no error will be thrown. It is important to note that all basic data types (e.g. int, float, etc.) as well as strings can be serialized.

Edit

After much thought, repeated reading of the code, I found your problem. When you do the following:

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

You are actually creating a brand new nameless inner class that implements MyInterface. However, because this is an inner class, it references its parent class, Activity. The activity is not serializable, so it throws a NotSerializableException.

How to solve it?

You will not be able to create a custom to-do class that can be serialized. However, there is a way out.

You can create a new class in a separate file (e.g. named CustomInterfaceImplementation) and create an instance of it, or create an internal class of your activity, which is static (note that this activity will not be found in your Create inside the onCreate() method, as this doesn’t make any sense. It should create activity scopes outside and inside any method scope).

So, for example, you can have something like this:

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

The above code can be either a static class in the CustomInterfaceImplementation MainActivity or a separate public Java class.

But what if I want to make a different mobile class from obj to obj?

As I said, making brand new classes that are serializable is difficult. However, you can extract all common code between all possible implementations and pass only variables that are likely to change. This way, you will maintain the Serializable character and potentially achieve your goals.

Related Problems and Solutions