zoukankan      html  css  js  c++  java
  • 【java】【android】序列化Serializable和继承

    今天在android的实验上,碰到个问题,花了1个多小时查出问题并解决。

    这个问题比较隐蔽,不了解的话会浪费很多时间。

    先看代码:

    在NewsListActivity.java中

    Intent intent = new Intent(NewsListActivity.this, NewsInfoActivity.class);
    intent.putExtra("ItemState", item);
    NewsListActivity.this.startActivity(intent);

    在NewsInfoActivity.java中

    if(intent.getExtras() != null){
        item = (RSSItem)intent.getExtras().getSerializable("ItemState");
    }

    这里要求RSSItem类必须能序列化,即实现Serializable接口

    我的RSSItem继承RSSObject类,而RSSObject类没有实现Serializable接口

    public class RSSItem extends RSSObject implements Serializable

    现在问题出现了,没有报编译错误,也没出现运行时错误,但就是NewsInfoActivity拿到的item的很多属性为null

    解决:父类RSSObject必须实现Serializable接口,就没问题了。

    http://www.cjsdn.net/post/view?bid=2&id=192312&sty=1&tpg=5&age=0

    一、序列化简介
    在这里我先简要介绍一下和序列化相关的一些概念,如果你觉得自己对序列化已经比较熟悉,那么跳过这一节,直接看下一节内容。
    序列化是Java中的一个非常重要的特性,通过序列化机制,我们可以将Java的对象变成流,或者存储在硬盘中,或者通过网络传输给网络的其他用户。而序列化在RMI,EJB中都有应用,可以说是构成J2EE的一个重要的技术。
    1)Serializable接口
    如果想让一个类可被序列化,那么这个类必须实现Serializable接口,这个接口本身没有任何方法和属性,它的作用只是为了标示一个类可以被序列化,这一个特性好像在Java里用的比较多,比如克隆也是采用了相同的机制。
    因此,如果我们想创建一个可以被序列化的类,我们可以像下面的代码一样做。
    import java.io.Serializable;
    public class SerialClass implements Serializable
    {
    private static final long serialVersionUID = -190734710746841476L;
    private String c;
    public int a;
    public String b;
    public int getA(){return a;}
    public String getB(){return b;}
    public void setA(int a){this.a = a;}
    public void setB(String b){this.b = b;}
    public String getC(){return c; }
    public void setC(String c){this.c = c; }
    从上面的例子我们可以看到,除了需要实现Serialzable接口外,一个可序列化的类和一个普通类没有什么大的区别。不过我们还是有一些特别的东西需要注意的。
    2)属性 serialVersionUID
    这个属性是一个私有的静态final属性,一般刚接触序列化的人会忽略这个属性,因为这个属性不是必须的。这个属性主要是为了保证一个可序列化类在不同的 Java编译器中,能保证相同的版本号,这样保证当这个类在不同的JVM中进行序列化与反序列化时不会出现InvalidClassException异常。
    3)属性与序列化
    那么我们再考虑另一个问题,是不是一个类实现了Serializable之后就可以看成是可序列化的类呢?答案是不行,实际上一个类是否可序列化还需要看这个类的属性,在Java规范中,一个类是否能序列化,不但取决于这个类是否实现Serializable接口,还取决于这个类中的属性是否可序列化。在上面的例子里,一共有三个属性,两个是String对象,一个是int类型的属性,实际上,String类是可序列化的(继承了Serializable 接口且它的属性都是可序列化的),而像int这样的基本数据类型在Java中被看成是可序列化的,因此我们可以确认上面的这个类是一个可序列化的类。那么现在我们已经创建了一个可序列化类,接下去的问题是怎么使用这个类,对它进行序列化与反序列化操作?
    4)ObjectOutputStream 和 ObjectInputStream类
    Jdk提供了两个IO流类进行序列化和反序列化操作,其中ObjectOutputStream中的writeObject方法对一个对象进行序列化工作;而ObjectInputStrem中的readObject方法则负责发序列化的操作。下面的例子完整的显示了一个类的序列化和反序列化操作。
    package serialtest;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    public class TestClass
    {
    public static void main(String[] args) throws Exception
    {
    SerialClass s = new SerialClass();
    s.setA(10);
    s.setB("hello");
    s.setC("world");
    //创建ObjectOutputStream对象,准备序列化对象s
    ObjectOutputStream oos = new ObjectOutputStream(
    new FileOutputStream("abc"));
    //调用writeObject将对象进行序列化,存储在文件abc中。
    oos.writeObjectMoon;
    oos.flush();
    oos.close();
    //创建ObjectInputStream对象,准备从文件abc中反序列化SerialClass对象
    ObjectInputStream ois = new ObjectInputStream(
    new FileInputStream("abc"));
    //调用readObject将存储在文件abc中的字节流反序列化为SerialClass对象。
    s = (SerialClass) ois.readObject();
    System.out.println(s.getA());
    System.out.println(s.getB());
    System.out.println(s.getC());
    }
    }
    执行程序,最后的结果应该是:
    10
    Hello
    World
    好了,序列化的基础知识就讲到这里。接下来我们看看继承对于序列化的影响。
    二、继承对序列化的影响
    我们现在把上面的例子做点变换,变成如下的形式。
    1)首先创建一个Interface。
    package serialtest;
    public interface SuperInterface
    {
    public int getA();
    public String getB();
    public void setA(int a);
    public void setB(String b);
    }
    2)创建一个抽象类实现SuperInterface接口,注意,这个类没有实现Serializable接口。
    package serialtest;
    public abstract class AbsSuperClass implements SuperInterface
    {
    public int a;
    public String b;
    public int getA() {return a;}
    public String getB(){return b; }
    public void setA(int a) {this.a = a;}
    public void setB(String b) {this.b = b;}
    }
    3)SerialClass类继承了AbSuperClass,同时它也实现了Serializable接口。
    package serialtest;
    import java.io.Serializable;
    public class SerialClass extends AbsSuperClass implements Serializable
    {
    private static final long serialVersionUID = -190734710746841476L;
    private String c;
    public String getC(){return c; }
    public void setC(String c) {this.c = c;}
    }
    这时候我们在运行Test,将会发现结果和第一节的例子不一样了,这时候结果将变成:
    0
    null
    world
    而导致这个结果的原因就在AbSuperClass上,因为AbSuperClass没有实现Serializable接口,所以它不可被序列化;但 SerialClass由于实现了Serializable接口而成为一个可序列化的类,这时候,属性c因为是SerialClass的类所以c的值在序列化时将被保存,而属性a和b是从AbSuperClass中继承而来,他们因为AbSuperClass的缘故而导致了它们的值不能在序列化是被保存。
    关于这一点,我在Java文档中也得到了证实,在Java doc中明确指出,如果一个类继承了一个非Serializable类时,如果想在序列化中保存父类的属性,则需要实现额外的代码显式地存储父类的属性值。
    最后再回到本文的初衷,诚然,这篇文章是以对象的序列化为主的,但最后我又要回到一个比较古老的话题上,那就是在软件开发的时候,继承到底该用到什么一种程度?毕竟,滥用继承对整个系统的影响将是深远的。

  • 相关阅读:
    SAP PI 如何实现消息定义查询
    EWM与ERP交互程序
    ITS Mobile Template interpretation failed. Template does not exist
    SAP Material Flow System (MFS) 物料流系统简介
    SAP EWM Table list
    EWM RF 屏幕增强
    SAP EWM TCODE list
    SAP扩展仓库管理(SAPEWM)在线研讨会笔记
    ERP与EWM集成配置ERP端组织架构(二)
    EWM RF(Radio Frequency)简介
  • 原文地址:https://www.cnblogs.com/549294286/p/2630466.html
Copyright © 2011-2022 走看看