精华内容
下载资源
问答
  • 2021-09-09 19:51:34

    java类尽量不实现Serializable接口

    Java内置序列化功能的主要场景

    • 在当前程序之外保存对象并在需要的时候重新获获取对象

    尽量不实现Serializable接口原因

    • 序列化不必要地对外公开了对象的物理实现
    • 序列化容易使一 个类对其最初的内部表示产生依赖
    • 编写正确的反序列化代码有很大的挑战
    • 序列化增大了安全风险
    • 列化增加了测试的难度

    除非必须使用的第三方接口要求必须实现Serializable接口,否则请选用其替

    更多相关内容
  • java对象实现Serializable接口 在还没有深入了解serializable接口之前,像很多程序员一样,以为一个对象实现serializable接口就被序列化了。 最近在接触ehcache缓存的时候,将对象缓存起来,该对象需要先实现...

    java对象实现Serializable接口
    在还没有深入了解serializable接口之前,像很多程序员一样,以为一个对象实现serializable接口就被序列化了。
    最近在接触ehcache缓存的时候,将对象缓存起来,该对象需要先实现Serializable接口,然而,我们会发现对象并没有真正的被序列化。
    下面让我们一起来总结一下Serializable接口的实现原理。
    当一个类实现了Seializable接口(该接口仅为标记接口,不包含任何方法定义),表示该类可以序列化,序列化的目的是将一个实现了Serializable接口的对象可以转换成一个字节序列,保存对象的状态。
    把该字节序列保存起来(例如:保存在一个文件里),以后可以随时将该字节序列恢复为原来的对象。甚至可以将该字节序列放到其他计算机上或者通过网络传输到其他计算机上恢复,只有该计算机平台存在相应的类就可以正常恢复为原来的对象。
    一个对象实现Serializable接口序列化,先要创建某些OutputStream对象,然后将其封装在一个ObjectOutputStream对象内,再调用writeObject()方法,即可序列化一个对象,反序列化,InputStream,再调用readObject()方法。(writeObject和readObject本身就是线程安全的,传输过程中是不允许被并发访问的,所以对象只能一个一个接连不断的传过来)。
    如果某个类能够被序列化,其子类也可以被序列化。声明为static和transient类型的成员数据不能被序列化。因为static代表类的状态,transient代表对象的临时数据, static对象变量在反序列化时取得的值为当前jvm中对应类中对应static变量的值,而transient(瞬态)关键字则一般用于标识那些在序列化时不需要传递的状态变量。
    Person类
    package org.test.domain;
     
    import java.io.Serializable;
     
    public class Person implements Serializable{
     
        /**
         * 
         */
        private static final long serialVersionUID = 1L;
        
        protected String name;
        protected transient int age;
        
        
        public Person(){}
        
        public Person(String name,int age){
            this.name = name;
            this.age = age;        
        }
        
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
     
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
        
        public String toString()
        {
            return "this is person:"+"name:"+this.name+"——age:"+this.age;
        }
    }

    User类
    package org.test.domain;
     
    import java.io.Serializable;
     
    public class User extends Person{
     
        /**
         * 
         */
        private static final long serialVersionUID = 1L;
        
        private String name;
        private String password;
        
        public User() {
            
        }
     
        public User(String name,String password,int age)
        {
            this.name = name;
            this.password = password;
            this.age = age;
        }
        
        public String getName() {
            return name;
        }
     
        public void setName(String name) {
            this.name = name;
        }
     
        public String getPassword() {
            return password;
        }
     
        public void setPassword(String password) {
            this.password = password;
        }
     
        public String toString()
        {
            return "this is user:"+"name:"+this.name+"——password:"+this.password+"——age:"+this.age;
        }
        
    }

    SerializableTest类
    package org.test.main;
     
    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
     
    import org.test.domain.Person;
    import org.test.domain.User;
     
    public class SerializableTest {
     
        public static void main(String[] args) {
            
            Person p1 = (Person)deSerialByte(serialByte(new User("user","1234",15)));
            
            //Person p2 = (Person)deSerialByte(serialByte(new Person("person",10)));
            
            System.out.println("p1:"+p1.toString());
            
            //System.out.println("p2:"+p2.toString());
        }
        
        //序列化一个对象(可以存储到一个文件也可以存储到字节数组)这里存储到自己数组
        public static byte[] serialByte(Object obj)
        {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ObjectOutputStream oos;
            try {
                oos = new ObjectOutputStream(baos);
                oos.writeObject(obj);
                oos.close();
                return baos.toByteArray();
            } catch (IOException e) {
                throw new RuntimeException(e.getMessage());
            }
        }
        
        //反序列化一个对象
        public static Object deSerialByte(byte[] by)
        {
            ObjectInputStream ois;
            try {
                ois = new ObjectInputStream(new ByteArrayInputStream(by));
                return ois.readObject();
            } catch (Exception e) {
                throw new RuntimeException(e.getMessage());
            }
        }
    }

    serialVersionUID作用: 
           序列化时为了保持版本的兼容性,即在版本升级时反序列化仍保持对象的唯一性。
    有两种生成方式:
           一个是默认的1L,比如:private static final long serialVersionUID = 1L;
           一个是根据类名、接口名、成员方法及属性等来生成一个64位的哈希字段,比如:
           private static final   long     serialVersionUID = xxxxL;

    当你一个类实现了Serializable接口,如果没有定义serialVersionUID,Eclipse会提供这个提示功能告诉你去定义 。在Eclipse中点击类中warning的图标一下,Eclipse就会自动给定两种生成的方式。如果不想定义它,在Eclipse的设置中也
           可以把它关掉的,设置如下: 
            Window ==> Preferences ==> Java ==> Compiler ==> Error/Warnings ==>
            Potential programming problems 
            将Serializable class without serialVersionUID的warning改成ignore即可。

    如果你没有考虑到兼容性问题时,就把它关掉,不过有这个功能是好的,只要任何类别实现了Serializable这个接口的话,如果没有加入serialVersionUID,Eclipse都会给你warning提示,这个serialVersionUID为了让该类别Serializable向后兼容。

    如果你的类Serialized存到硬盘上面后,可是后来你却更改了类别的field(增加或减少或改名),当你Deserialize时,就会出现Exception的,这样就会造成不兼容性的问题。

    但当serialVersionUID相同时,它就会将不一样的field以type的预设值Deserialize,可避开不兼容性问题。

    注意以下几点:

    1、若继承的父类没有实现Serializable接口,但是又想让子类可序列化,子类实现Serializable接口,子类必须有可访问的无参构造方法,用于保存和恢复父类的public或protected或同包下的package字段的状态,否则在序列化或反序列化时会抛出RuntimeException异常,对于序列化后的子类,在进行反序列化时,理论上无法初始化父类中private(不可访问)对象变量的状态或值。

    2、在对可序列化类中的属性进行序列化时,如果遇到不可序列化的对象变量,此时会针对不可序列化的类抛出NotSerializableException异常

    3、对于可序列化的非数组类,强烈建议显示声明static型、long型、final型serialVersionUID字段用于标识当前序列化类的版本号,否则在跨操作系统、跨编译器之间进行序列化和反序列化时容易出现InvalidClassException异常
     

    展开全文
  • 项目上有很多的pojo,entity,实体类实现serializable接口: 序列化是指在对象和对象网络进行传输过程中,将对象的状态信息转换为可以存储或传输的形式的过程. 比如说上传文件. Serializable接口是启用其序列化功能的...

    项目上有很多的pojo,entity,实体类实现serializable接口:

    序列化是指在对象和对象网络进行传输过程中,将对象的状态信息转换为可以存储或传输的形式的过程.

    比如说上传文件.

    Serializable接口是启用其序列化功能的接口。实现java.io.Serializable 接口的类是可序列化的。没有实现此接口的类将不能使它们的任意状态被序列化或逆序列化。

    所谓的Serializable,就是java提供的通用数据保存和读取的接口。至于从什么地方读出来和保存到哪里去都被隐藏在函数参数的背后了。这样子,任何类型只要实现了Serializable接口,就可以被保存到文件中,或者作为数据流通过网络发送到别的地方。也可以用管道来传输到系统的其他程序中。这样子极大的简化了类的设计。

     

    展开全文
  • Serializable是什么,为什么要实现Serializable接口

    千次阅读 多人点赞 2020-08-06 13:45:07
    Serializable是什么,为什么要实现Serializable接口?什么是Serializable接口什么是序列化?为什么要序列化对象什么情况下需要序列化?为什么要定义serialversionUID变量序列化的使用关于serialVersionUID 一般情况...

    一般情况下,我们在定义实体类时会实现Serializable接口,例如:
    在这里插入图片描述

    什么是Serializable接口

    一个对象序列化的接口,一个类只有实现了Serializable接口,它的对象才能被序列化。

    Serializable是java.io包中定义的、用于实现Java类的序列化操作而提供的一个语义级别的接口。

    Serializable序列化接口没有任何方法或者字段,只是用于标识可序列化的语义。

    实现了Serializable接口的类可以被ObjectOutputStream转换为字节流,同时也可以通过ObjectInputStream再将其解析为对象。例如,我们可以将序列化对象写入文件后,再次从文件中读取它并反序列化成对象,也就是说,可以使用表示对象及其数据的类型信息和字节在内存中重新创建对象。

    什么是序列化?

    序列化是将对象状态转换为可保持或传输的格式的过程。与序列化相对的是反序列化,它将流转换为对象。这两个过程结合起来,可以轻松地存储和传输数据。

    为什么要序列化对象

    把对象转换为字节序列的过程称为对象的序列化

    把字节序列恢复为对象的过程称为对象的反序列化

    序列化对于面向对象的编程语言来说是非常重要的,因为无论什么编程语言,其底层涉及IO操作的部分还是由操作系统其帮其完成的,而底层IO操作都是以字节流的方式进行的,所以写操作都涉及将编程语言数据类型转换为字节流,而读操作则又涉及将字节流转化为编程语言类型的特定数据类型。

    什么情况下需要序列化?

    当我们需要把对象的状态信息通过网络进行传输,或者需要将对象的状态信息持久化,以便将来使用时都需要把对象进行序列化。

    那为什么还要继承Serializable。那是存储对象在存储介质中,以便在下次使用的时候,可以很快捷的重建一个副本。

    或许你会问,我在开发过程中,实体并没有实现序列化,但我同样可以将数据保存到mysql、Oracle数据库中,为什么非要序列化才能存储呢?

    我们来看看Serializable到底是什么,跟进去看一下,我们发现Serializable接口里面竟然什么都没有,只是个空接口
    在这里插入图片描述

    一个接口里面什么内容都没有,我们可以将它理解成一个标识接口。

    比如在课堂上有位学生遇到一个问题,于是举手向老师请教,这时老师帮他解答,那么这位学生的举手其实就是一个标识,自己解决不了问题请教老师帮忙解决。在Java中的这个Serializable接口其实是给jvm看的,通知jvm,我不对这个类做序列化了,你(jvm)帮我序列化就好了。

    Serializable接口就是Java提供用来进行高效率的异地共享实例对象的机制,实现这个接口即可。

    为什么要定义serialversionUID变量

    首先看一下接口里的说明:
    在这里插入图片描述
    可以发现如果我们不自定义serialversionUID,系统就会生成一个默认的serialversionUID。
    在这里插入图片描述
    从注释中我们可以看到,它强烈建议我们自己定义一个serialversionUID,因为默认生成的serialversionUID对class极其敏感,在反序列化的时候很容易抛出InvalidClassException异常。

    序列化的使用

    下面我们可以通过例子来实现将序列化的对象存储到文件,然后再将其从文件中反序列化为对象,代码示例如下:

    先定义一个序列化对象User:

      public class User implements Serializable { 
            private static final long serialVersionUID = 1L; 
         
            private String userId; 
            private String userName; 
         
            public User(String userId, String userName) { 
                this.userId = userId; 
                this.userName = userName; 
            } 
        } 
    

    然后我们编写测试类,来对该对象进行读写操作,我们先测试将该对象写入一个文件:

     public class SerializableTest { 
         
            /** 
             * 将User对象作为文本写入磁盘 
             */ 
            public static void writeObj() { 
                User user = new User("1001", "Joe"); 
                try { 
                    ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("/Users/guanliyuan/user.txt")); 
                    objectOutputStream.writeObject(user); 
                    objectOutputStream.close(); 
                } catch (IOException e) { 
                    e.printStackTrace(); 
                } 
            } 
         
            public static void main(String args[]) { 
                writeObj(); 
            } 
        } 
    

    运行上述代码,我们就将User对象及其携带的数据写入了文本user.txt中。

    接下来,我们继续编写测试代码,尝试将之前持久化写入user.txt文件的对象数据再次转化为Java对象,代码如下:

    public class SerializableTest {
        /**
         * 将类从文本中提取并赋值给内存中的类
         */
        public static void readObj() {
            try {
                ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("/Users/guanliyuan/user.txt"));
                try {
                    Object object = objectInputStream.readObject();
                    User user = (User) object;
                    System.out.println(user);
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
    
        public static void main(String args[]) {
            readObj();
        }
    }
    

    通过反序列化操作,可以再次将持久化的对象字节流数据通过IO转化为Java对象,结果如下:

    cn.wudimanong.serializable.User@6f496d9f
    

    序列化与反序列化操作过程就是这么的简单。只需要将User写入到文件中,然后再从文件中进行恢复,恢复后得到的内容与之前完全一样,但是两者是不同的对象。

    关于serialVersionUID

    对于JVM来说,要进行持久化的类必须要有一个标记,只有持有这个标记JVM才允许类创建的对象可以通过其IO系统转换为字节数据,从而实现持久化,而这个标记就是Serializable接口。而在反序列化的过程中则需要使用serialVersionUID来确定由那个类来加载这个对象,所以我们在实现Serializable接口的时候,一般还会要去尽量显示地定义serialVersionUID。

    这个serialVersionUID的详细的工作机制是:在序列化的时候系统将serialVersionUID写入到序列化的文件中去,当反序列化的时候系统会先去检测文件中的serialVersionUID是否跟当前的文件的serialVersionUID是否一致,如果一直反序列化不成功,就说明当前类跟序列化后的类发生了变化,比如是成员变量的数量或者是类型发生了变化,那么在反序列化时就会发生crash,并且回报出错误:

    java.io.InvalidClassException: User; local class incompatible: stream classdesc serialVersionUID = -1451587475819212328, local class serialVersionUID = -3946714849072033140at 
    java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:699)at 
    java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1885)at 
    java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1751)at
    java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2042)at 
    java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1573)at 
    java.io.ObjectInputStream.readObject(ObjectInputStream.java:431)at 
    Main.readUser(Main.java:32)at Main.main(Main.java:10)
    

    刚开始提到了,serialVersionUID要不要指定呢?如果不指定会出现什么样的后果?如果指定了以后后边的值又代表着什么意思呢?既然系统指定了这个字段,那么肯定是有它的作用的。

    如果我们在序列化中没有显示地声明serialVersionUID,则序列化运行时将会根据该类的各个方面计算该类默认的serialVersionUID值。但是,Java官方强烈建议所有要序列化的类都显示地声明serialVersionUID字段,因为如果高度依赖于JVM默认生成serialVersionUID,可能会导致其与编译器的实现细节耦合,这样可能会导致在反序列化的过程中发生意外的InvalidClassException异常。因此,为了保证跨不同Java编译器实现的serialVersionUID值的一致,实现Serializable接口的必须显示地声明serialVersionUID字段。

    此外serialVersionUID字段地声明要尽可能使用private关键字修饰,这是因为该字段的声明只适用于声明的类,该字段作为成员变量被子类继承是没有用处的!有个特殊的地方需要注意的是,数组类是不能显示地声明serialVersionUID的,因为它们始终具有默认计算的值,不过数组类反序列化过程中也是放弃了匹配serialVersionUID值的要求。

    转自:

    https://baijiahao.baidu.com/s?id=1633305649182361563&wfr=spider&for=pc

    https://mp.weixin.qq.com/s/Zpb2OuZxJpWX2mow3qd-xg

    展开全文
  • Serializable接口的使用 一.引入问题 一般情况下,我们在定义实体类时会继承Serializable接口,类似这样: import java.io.Serializable; public class Person implements Serializable { String name; int age; ...
  • 为了网络进行传输或者持久化 什么是序列化 将对象的状态信息转换为可以存储或传输的形式的过程 ...除了实现Serializable接口还有什么序列化方式 Json序列化 FastJson序列化 ProtoBuff序列化
  • 在开发过程中,看到java类不管是vo,dto,还是po类都需要实现java.io.Serializable 这个没有属性和方法的空接口(public interface Serializable {})。vo类实现如public class SemesterVo implements Serializable {...
  • 文章目录1、方式一(实现Serializable接口,通过序列化流)2、方式二 (实现Externalizable接口,重写writeExternal和readExternal方法) 对象序列化的目标是将对象保存到磁盘中,或允许在网络中直接传输对象。对象...
  • 在Java编程中我们会看到源码中或者别人代码中很多实体Bean都实现了Serializable接口,但是我很多实体在使用中并没有序列化也能...由此引发了我的疑问,到底需不要实现Serializable接口?答案是必要,请由我娓娓道来。
  • 只有实现serializable接口的类的对象才能被实例化。 什么情况下会用到序列化? 1.当你想把内存中的对象写入到硬盘时 2.当你想用套接字在网络上传输对象时 3.当你想通过RMI调用对象时 (RMI是什么东西...
  • 实现Serializable接口

    2016-09-19 15:43:19
    序列化是将一个实现Serializable接口的对象转化成一个字节序列(一组byte)。可以把该字节序列保存起来,以后要用这个对象时候,就能把这些byte数据恢复出来,并据此重新构建那个对象。甚至可以将该字节序列放到其他...
  • 1、为什么要实现serializable 接口 实现了serializable接口的类,可以被 ObjectOutputStream 转换为字节流写入文件,同时也可以被ObjectInputStream再转换为内存中的对象。 2、对象序列化用在什么场景 将内存中的...
  • java类需不需要实现Serializable接口

    千次阅读 2021-03-02 15:24:58
    java类需不需要实现Serializable接口 转换为json字符串 不需要实现Serializable接口 只是转换为json字符串的形式与网络打交道,那么就不需要实现Serializable接口 RPC调用 需要实现Serializable接口 一般来说如果你...
  • 在学习序列化的时候产生的问题,Serializable接口是一个空接口,那为什么实现Serializable接口就能序列化呢? 序列化主要是通过ObjectOutputSteam中的writeObject方法。在writeObject方法中会判断对象是否是...
  • 工作中我们经常在进行持久化操作和返回数据时都会使用到javabean来统一封装参数,方便操作,一般我们也都会实现Serializable接口,那么问题来了,首先:为什么要进行序列化;其次:每个实体bean都必须实现...
  • 只有以下类型才能正常序列化: String Array Enum Serializable   所以我们自定义的类型要想实现序列化,必须实现Serializable接口,从而变成Serializable类型。   在这里顺便说个与本文章无关的却被很多人忽视...
  • 如果要序列化某些类的对象,这些类就必须实现Serializable接口。Serializable是一个空接口,没有什么具体内容,它的目的只是简单的标识一个类的对象可以被序列化。 为什么要进实现Serializable接口:为了保存在内存...
  • Serializable:Serializable接口是启用其序列化功能的接口。实现java.io.Serializable 接口的类是可序列化的。没有实现此接口的类将不能使它们的任意状态被 序列化或逆序列化。 一般来说,Serializable适用于...
  • ###java 序列化为什么要实现Serializable接口 ####什么是java序列化 1.java序列化是将对象写入字节流,将对象换成字节的表现形式 ####java实现序列化的意义 1.序列化之后的java对象,可以以字节流形式用于数据持久化...
  • java对象实现Serializable接口(整理)

    千次阅读 2017-11-14 11:03:22
    在还没有深入了解serializable接口之前,像很多程序员一样,以为一个对象实现serializable接口就被序列化了。 最近在接触ehcache缓存的时候,将对象缓存起来,该对象需要先实现Serializable接口,然而,我们会...
  • 如果你的项目中有如下场景的任意一个场景,都需要实现Serializable: 使用ObjectOutputStream序列化对象为二进制。 使用RPC框架(如Dubbo、Thrift等)进行数据传输。 直接使用RedisTemplate进行操作。 原因是以上...
  • 在日常编码中,经常看到一些实体类实现Serializable接口,不禁会问,为什么要实现这个接口?浅显的回答就是为了序列化,那么,再深挖一点呢? 为什么要序列化? 网络中的数据传输和磁盘的数据存储都是二进制方式,...
  • Java序列化和反序列化为什么要实现Serializable接口

    千次阅读 多人点赞 2019-08-27 11:49:37
    最近公司的在做服务化, 需要把所有model包里的类都实现Serializable接口, 同时还要显示指定serialVersionUID的值. 听到这个需求, 我脑海里就突然出现了好几个问题, 比如说: (1) 序列化和反序列化是什么? (2) 实现...
  • 一句话解释就是:在反序列化过程中用于验证序列...默认的 serialVersionUID 对类的详细信息具有较高的敏感性,根据编译器实现的不同可能千差万别,这样在反序列化过程中可能会导致意外的 InvalidClassException产生。
  • 这时候,就又有一个问题,既然实体类的变量都已经帮助我们实现了序列化,为什么我们仍然要显示的让类实现serializable接口呢? 首先,序列化的目的有两个,**第一个是便于存储,第二个是便于传输。**我们一般的...
  • 有个常见的误解就是,"所有实体类都要实现Serializable接口",其实实体类不一定要实现Serializable接口,只有JDK自带的序列化才需要这么做,使用json序列化就不需要了。 一、什么是序列化和反序列化? 序列化:...
  • 序列化与反序列化序列化是将对象的状态信息(也就是...Serializable接口 implements Serializable只是为了标注该对象是可被序列化的。 serialVersionUID 当创建一个类并实现Serializable之后,在你的类名上:Alt...
  • 一个java类什么时候需要实现Serializable接口 1.什么是Serializable接口 一个对象序列化的接口。一个类只有实现了Serializable接口,它的对象才能被序列化。 2.什么是序列化? 将对象的状态信息转换为可以存储或...
  • 对于 Java 的序列化,我一直停留在最浅显的认知上——把那个要序列化的类实现 Serializbale 接口就可以了。我不愿意做更深入的研究,因为会用就行了嘛。 但随着时间的推移,见到 Serializbale 的次数越来越多,我便...
  • 为什么实体类要实现serializable接口 序列化 最重要的两个原因是:  1、将对象的状态保存在存储媒体中以便可以在以后重新创建出完全相同的副本;  2、按值将对象从一个应用程序域发送至另一个应用程序域。   实现...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 205,806
精华内容 82,322
关键字:

怎么实现serializable接口