Java 带有自定义数据包的 NotSerializableException

Java NotSerializableException with custom DataPackage

我目前正在为未来的项目开发一个简单的服务器-客户端结构。我决定最好用自定义 header-information 创建自己的 data-package,例如 local/public ip、时间戳等。以下是我想出的 class :

public class DataPackage {
    private Object object;
    private Date time;
    private long timeMs;
    private boolean responded;
    private String publicIp;
    private String internalIp;
    private int hash;

    public DataPackage(Object object) {
        this.object = object;
        this.responded = false;
        this.time = Calendar.getInstance().getTime();
        this.timeMs = System.currentTimeMillis();
        this.publicIp = this.generatePublicIp();
        this.internalIp = this.generateInternalIp();
        this.hash = System.identityHashCode(this);
    }

    private String generatePublicIp() {
        try {
            URL whatismyip = new URL("http://checkip.amazonaws.com");
            BufferedReader in = new BufferedReader(new InputStreamReader(whatismyip.openStream()));

            return in.readLine();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    private String generateInternalIp() {
        try {
            return InetAddress.getLocalHost().getHostAddress();
        } catch (UnknownHostException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }

}

(我删除了 getter 和 setter)

我决定使用 object,这样我就可以在 class 中发送任何内容。它编译得很好,但如果我尝试发送一个简单的字符串,打包在 class 中,我会得到一个 NotSerializableException。是否有任何属性或字段无法转换为流,或者我应该将 class 更改为通用的?我不是流和网络方面的专家,所以我非常感谢我能得到的每一点帮助和解释。

注意:我不是以英语为母语的人,如有任何 spelling/grammar 问题,请原谅。

当您的对象不可序列化时抛出

java.io.NotSerializableException,这意味着您的 object 或该对象的任何 non-transient 属性 未实现 Serializable界面。在您的情况下, DataPackage 不是可序列化的。 Serializable 是一个标记 interface,它基本上告诉 JVM Serializable 类型的任何 instance 都可以序列化。在这里您可以浏览 Serializable and NotSerializableException.

的文档

您应该实现 Serializable 接口,以便 class 通过网络传输。

将 class 的第一行更改为:

import java.io.Serializable;
public class DataPackage implements Serializable{

您的 class 应该实现 Serializable 接口。

另请注意,您的 class 的每个 属性,在您的情况下 object 也应实现此接口,以便序列化正常工作。

所以我会考虑使这个 class 通用以强制对象实现 Serializable 接口。

编辑: 例如,如果您尝试序列化包含 ByteBuffer(不可序列化)的 DataPackage,如下所示:new DataPackage(ByteBuffer.allocate(1)),您将得到一个异常.

试试这个:

    import java.io.Serializable;

    public class DataPackage<T extends Serializable> implements Serializable{
    private T object;
    private Date time;
    private long timeMs;
    private boolean responded;
    private String publicIp;
    private String internalIp;
    private int hash;

    public DataPackage(T object) {
        this.object = object;
        this.responded = false;
        this.time = Calendar.getInstance().getTime();
        this.timeMs = System.currentTimeMillis();
        this.publicIp = this.generatePublicIp();
        this.internalIp = this.generateInternalIp();
        this.hash = System.identityHashCode(this);
    }

    private String generatePublicIp() {
        try {
            URL whatismyip = new URL("http://checkip.amazonaws.com");
            BufferedReader in = new BufferedReader(new InputStreamReader(whatismyip.openStream()));

            return in.readLine();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    private String generateInternalIp() {
        try {
            return InetAddress.getLocalHost().getHostAddress();
        } catch (UnknownHostException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }

}

通过这种方式,您可以确保您尝试发送的对象都是可序列化的。

如果你不想使用泛型,那么像这样制作可序列化类型的 object :

import java.io.Serializable;

        public class DataPackage implements Serializable{
        private Serializable object;
        private Date time;
        private long timeMs;
        private boolean responded;
        private String publicIp;
        private String internalIp;
        private int hash;

        public DataPackage(Serializable object) {
            this.object = object;
            this.responded = false;
            this.time = Calendar.getInstance().getTime();
            this.timeMs = System.currentTimeMillis();
            this.publicIp = this.generatePublicIp();
            this.internalIp = this.generateInternalIp();
            this.hash = System.identityHashCode(this);
        }

        private String generatePublicIp() {
            try {
                URL whatismyip = new URL("http://checkip.amazonaws.com");
                BufferedReader in = new BufferedReader(new InputStreamReader(whatismyip.openStream()));

                return in.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }

        private String generateInternalIp() {
            try {
                return InetAddress.getLocalHost().getHostAddress();
            } catch (UnknownHostException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return null;
        }

    }