首先,需要紀錄的是在項目中出現的一個問題,序列化一個內部類,出現NotSerializableException.
解決方法有兩個,第一種方法是最開始自己的處理,使用writeObject和readObject來實現自定義序列化,這個有些
繁雜,需要對每個實例字段進行序列化,不然,當你反序列化時,得到的對象的字段都是默認值,如int=0,string=null.

 ...
ExpandedBlockStart.gif ContractedBlock.gifpublic class MsgBean implements Serializable  dot.gif{
InBlock.gif
ExpandedSubBlockStart.gif ContractedSubBlock.gif        /** *//**
InBlock.gif         * Comment for <code>serialVersionUID</code>
ExpandedSubBlockEnd.gif         */
InBlock.gif        private static final long serialVersionUID = 1L;
InBlock.gif
InBlock.gif        private int msgType;
InBlock.gif
InBlock.gif        private String mName;
InBlock.gif
ExpandedSubBlockStart.gif ContractedSubBlock.gif        public String getMName()  dot.gif{
InBlock.gif            return mName;
ExpandedSubBlockEnd.gif        }
InBlock.gif
ExpandedSubBlockStart.gif ContractedSubBlock.gif        public void setMName(String name)  dot.gif{
InBlock.gif            mName = name;
ExpandedSubBlockEnd.gif        }
InBlock.gif
ExpandedSubBlockStart.gif ContractedSubBlock.gif        public int getMsgType()  dot.gif{
InBlock.gif            return msgType;
ExpandedSubBlockEnd.gif        }
InBlock.gif
ExpandedSubBlockStart.gif ContractedSubBlock.gif        public void setMsgType(int msgType)  dot.gif{
InBlock.gif            this.msgType = msgType;
ExpandedSubBlockEnd.gif        }
InBlock.gif
ExpandedSubBlockStart.gif ContractedSubBlock.gif        private void writeObject(ObjectOutputStream out) throws IOException  dot.gif{
InBlock.gif            out.writeObject(getMName());
InBlock.gif            out.writeObject(new Integer(getMsgType()));
ExpandedSubBlockEnd.gif        }
InBlock.gif
InBlock.gif        private void readObject(ObjectInputStream in) throws IOException,
ExpandedSubBlockStart.gif ContractedSubBlock.gif                ClassNotFoundException  dot.gif{
InBlock.gif            setMName((String) in.readObject());
InBlock.gif            setMsgType((Integer)in.readObject());
ExpandedSubBlockEnd.gif        }
InBlock.gif
ExpandedSubBlockStart.gif ContractedSubBlock.gif        public String toString()  dot.gif{
InBlock.gif            return "The object's class is MsgBean,field:mName=" + mName
InBlock.gif                    + ",msgType=" + msgType;
ExpandedSubBlockEnd.gif        }
ExpandedBlockEnd.gif    }

,後來在網上找找,發現只需要將該內部類聲明為static,即可.這是因為內部非靜態類會存在一個隱含的到外部

類的引用(外部類.this),所以當序類化內部類時,會關聯序列化外部類,恰恰外部類沒有實現Serializable接口,就會

出現這個錯誤.下面是改過後的.

ExpandedBlockStart.gif ContractedBlock.gifpublic static class MsgBean implements Serializable  dot.gif{
InBlock.gif
ExpandedSubBlockStart.gif ContractedSubBlock.gif        /** *//**
InBlock.gif         * Comment for <code>serialVersionUID</code>
ExpandedSubBlockEnd.gif         */
InBlock.gif        private static final long serialVersionUID = 1L;
InBlock.gif
InBlock.gif        private int msgType;
InBlock.gif
InBlock.gif        private String mName;
InBlock.gif
ExpandedSubBlockStart.gif ContractedSubBlock.gif        public String getMName()  dot.gif{
InBlock.gif            return mName;
ExpandedSubBlockEnd.gif        }
InBlock.gif
ExpandedSubBlockStart.gif ContractedSubBlock.gif        public void setMName(String name)  dot.gif{
InBlock.gif            mName = name;
ExpandedSubBlockEnd.gif        }
InBlock.gif
ExpandedSubBlockStart.gif ContractedSubBlock.gif        public int getMsgType()  dot.gif{
InBlock.gif            return msgType;
ExpandedSubBlockEnd.gif        }
InBlock.gif
ExpandedSubBlockStart.gif ContractedSubBlock.gif        public void setMsgType(int msgType)  dot.gif{
InBlock.gif            this.msgType = msgType;
ExpandedSubBlockEnd.gif        }
InBlock.gif
ExpandedSubBlockStart.gif ContractedSubBlock.gif        public String toString()  dot.gif{
InBlock.gif            return "The object's class is MsgBean,field:mName=" + mName
InBlock.gif                    + ",msgType=" + msgType;
ExpandedSubBlockEnd.gif        }
ExpandedBlockEnd.gif    }

好了,上面只是題外話.

我們在規劃序列化對象時,一般要考慮序列化的性能,所以對象不能太大,層次也不能太多.從這方面來考慮,
可以選擇序列化完整的一個類,或是只是針對字段來進行序列化.若是用于分布式中數據的傳輸,那應該是後
一種最好了.
下面來看第一種方法的一個例子
序列化對象

ContractedBlock.giftry  dot.gif{
InBlock.gif            MsgBean msgBean = new MsgBean();
InBlock.gif            msgBean.setMName(this.mName);
InBlock.gif            msgBean.setMsgType(msgtype);
InBlock.gif            ByteArrayOutputStream bytearrayoutputstream = null;
InBlock.gif            ObjectOutputStream objectoutputstream = null;
ExpandedSubBlockStart.gif ContractedSubBlock.gif            try  dot.gif{
InBlock.gif                bytearrayoutputstream = new ByteArrayOutputStream();
InBlock.gif                objectoutputstream = new ObjectOutputStream(
InBlock.gif                        bytearrayoutputstream);
InBlock.gif                objectoutputstream.writeObject(msgBean);
InBlock.gif                this.channel.send(new Message(null, null, bytearrayoutputstream
InBlock.gif                        .toByteArray()));
ExpandedSubBlockStart.gif ContractedSubBlock.gif            } finally  dot.gif{
InBlock.gif                if (objectoutputstream != null)
InBlock.gif                    objectoutputstream.close();
InBlock.gif                if (bytearrayoutputstream != null)
InBlock.gif                    bytearrayoutputstream.close();
ExpandedSubBlockEnd.gif            }
ExpandedBlockStart.gif ContractedBlock.gif        } catch (Exception e)  dot.gif{
InBlock.gif            logger.error("Jgroups send msg exception,msgtype=" + msgtype
InBlock.gif                    + ",mName=" + mName, e);
ExpandedBlockEnd.gif        }

反序列化

public void receive(Message arg0) {
    byte[] buf = arg0.getRawBuffer();
None.gifByteArrayInputStream bytearrayinputstream = null;
None.gif        ObjectInputStream objectinputstream = null;
ExpandedBlockStart.gif ContractedBlock.gif        try  dot.gif{
ExpandedSubBlockStart.gif ContractedSubBlock.gif            try  dot.gif{
InBlock.gif                bytearrayinputstream = new ByteArrayInputStream(buf, arg0
      .getOffset(), arg0.getLength());
InBlock.gif                objectinputstream = new ObjectInputStream(bytearrayinputstream);
InBlock.gif                MsgBean msgBean = (MsgBean) objectinputstream.readObject();
InBlock.gif                if (logger.isDebugEnabled())
InBlock.gif                    logger.debug(msgBean.toString());         
ExpandedSubBlockStart.gif ContractedSubBlock.gif            } finally  dot.gif{
InBlock.gif                if (objectinputstream != null)
InBlock.gif                    objectinputstream.close();
InBlock.gif                if (bytearrayinputstream != null)
InBlock.gif                    bytearrayinputstream.close();
ExpandedSubBlockEnd.gif            }
ExpandedBlockStart.gif ContractedBlock.gif        } catch (Exception e)  dot.gif{
InBlock.gif            logger.error("Received message and process exception.", e);
ExpandedBlockEnd.gif        }
}

java对象实例id java对象实例化的方法_java对象实例id

另外一種方法,是在jgroups的demo中看到的,

首先定義了一個公共的序列化接口

java对象实例id java对象实例化的方法_反序列化_02

java对象实例id java对象实例化的方法_java_03

None.gifpackage org.jgroups.util;
None.gif
None.gifimport java.io.DataInputStream;
None.gifimport java.io.DataOutputStream;
None.gifimport java.io.IOException;
None.gif
ExpandedBlockStart.gif ContractedBlock.gif/** *//**
InBlock.gif * Implementations of Streamable can add their state directly to the output stream, enabling them to bypass costly
InBlock.gif * serialization
InBlock.gif * @author Bela Ban
InBlock.gif * @version $Id: Streamable.java,v 1.2 2005/07/25 16:21:47 belaban Exp $
ExpandedBlockEnd.gif */
ExpandedBlockStart.gif ContractedBlock.gifpublic interface Streamable  dot.gif{
InBlock.gif
ExpandedSubBlockStart.gif ContractedSubBlock.gif    /** *//** Write the entire state of the current object (including superclasses) to outstream.
ExpandedSubBlockEnd.gif     * Note that the output stream <em>must not</em> be closed */
InBlock.gif    void writeTo(DataOutputStream out) throws IOException;
InBlock.gif
ExpandedSubBlockStart.gif ContractedSubBlock.gif    /** *//** Read the state of the current object (including superclasses) from instream
ExpandedSubBlockEnd.gif     * Note that the input stream <em>must not</em> be closed */
InBlock.gif    void readFrom(DataInputStream in) throws IOException, IllegalAccessException, InstantiationException;
ExpandedBlockEnd.gif}

然後將需要序列化的類實現這個方法

java对象实例id java对象实例化的方法_反序列化_02

java对象实例id java对象实例化的方法_java_03

// $Id: DrawCommand.java,v 1.6 2006/10/09 11:35:46 belaban Exp $
None.gif
None.gifpackage org.jgroups.demos;
None.gif
None.gifimport org.jgroups.util.Streamable;
None.gif
None.gifimport java.io.DataOutputStream;
None.gifimport java.io.IOException;
None.gifimport java.io.DataInputStream;
None.gif
ExpandedBlockStart.gif ContractedBlock.gif/** *//**
InBlock.gif * Encapsulates information about a draw command.
InBlock.gif * Used by the {@link Draw} and other demos.
InBlock.gif *
ExpandedBlockEnd.gif */
ExpandedBlockStart.gif ContractedBlock.gifpublic class DrawCommand implements Streamable  dot.gif{
InBlock.gif    static final byte DRAW=1;
InBlock.gif    static final byte CLEAR=2;
InBlock.gif    byte mode;
InBlock.gif    int x=0;
InBlock.gif    int y=0;
InBlock.gif    int r=0;
InBlock.gif    int g=0;
InBlock.gif    int b=0;
InBlock.gif
ExpandedSubBlockStart.gif ContractedSubBlock.gif    public DrawCommand()  dot.gif{ // needed for streamable
ExpandedSubBlockEnd.gif    }
InBlock.gif
ExpandedSubBlockStart.gif ContractedSubBlock.gif    DrawCommand(byte mode)  dot.gif{
InBlock.gif        this.mode=mode;
ExpandedSubBlockEnd.gif    }
InBlock.gif
ExpandedSubBlockStart.gif ContractedSubBlock.gif    DrawCommand(byte mode, int x, int y, int r, int g, int b)  dot.gif{
InBlock.gif        this.mode=mode;
InBlock.gif        this.x=x;
InBlock.gif        this.y=y;
InBlock.gif        this.r=r;
InBlock.gif        this.g=g;
InBlock.gif        this.b=b;
ExpandedSubBlockEnd.gif    }
InBlock.gif
InBlock.gif
ExpandedSubBlockStart.gif ContractedSubBlock.gif    public void writeTo(DataOutputStream out) throws IOException  dot.gif{
InBlock.gif        out.writeByte(mode);
InBlock.gif        out.writeInt(x);
InBlock.gif        out.writeInt(y);
InBlock.gif        out.writeInt(r);
InBlock.gif        out.writeInt(g);
InBlock.gif        out.writeInt(b);
ExpandedSubBlockEnd.gif    }
InBlock.gif
ExpandedSubBlockStart.gif ContractedSubBlock.gif    public void readFrom(DataInputStream in) throws IOException, IllegalAccessException, InstantiationException  dot.gif{
InBlock.gif        mode=in.readByte();
InBlock.gif        x=in.readInt();
InBlock.gif        y=in.readInt();
InBlock.gif        r=in.readInt();
InBlock.gif        g=in.readInt();
InBlock.gif        b=in.readInt();
ExpandedSubBlockEnd.gif    }
InBlock.gif
InBlock.gif
ExpandedSubBlockStart.gif ContractedSubBlock.gif    public String toString()  dot.gif{
InBlock.gif        StringBuffer ret=new StringBuffer();
ExpandedSubBlockStart.gif ContractedSubBlock.gif        switch(mode)  dot.gif{
InBlock.gif            case DRAW: ret.append("DRAW(" + x + ", " + y + ") [" + r + '|' + g + '|' + b + ']');
InBlock.gif                break;
InBlock.gif            case CLEAR: ret.append("CLEAR");
InBlock.gif                break;
InBlock.gif            default:
InBlock.gif                return "<undefined>";
ExpandedSubBlockEnd.gif        }
InBlock.gif        return ret.toString();
ExpandedSubBlockEnd.gif    }
InBlock.gif
ExpandedBlockEnd.gif}

序列化

 ContractedBlock.gifpublic void sendClearPanelMsg()  dot.gif{
InBlock.gif        int                  tmp[]=new int[1]; tmp[0]=0;
InBlock.gif        DrawCommand          comm=new DrawCommand(DrawCommand.CLEAR);
InBlock.gif
ExpandedSubBlockStart.gif ContractedSubBlock.gif        try  dot.gif{
InBlock.gif            byte[] buf=Util.streamableToByteBuffer(comm);
InBlock.gif            channel.send(new Message(null, null, buf));
ExpandedSubBlockEnd.gif        }
ExpandedSubBlockStart.gif ContractedSubBlock.gif        catch(Exception ex)  dot.gif{
InBlock.gif            System.err.println(ex);
ExpandedSubBlockEnd.gif        }
ExpandedBlockEnd.gif    }

java对象实例id java对象实例化的方法_java对象实例id_06

反序列化

public void receive(Message msg)  dot.gif{
InBlock.gif        byte[] buf=msg.getRawBuffer();
ExpandedSubBlockStart.gif ContractedSubBlock.gif        if(buf == null)  dot.gif{
InBlock.gif            System.err.println("received null buffer from " + msg.getSrc() + ", headers: " + msg.getHeaders());
InBlock.gif            return;
ExpandedSubBlockEnd.gif        }
InBlock.gif
ExpandedSubBlockStart.gif ContractedSubBlock.gif        try  dot.gif{
InBlock.gif            DrawCommand comm=(DrawCommand)Util.streamableFromByteBuffer(DrawCommand.class, buf, msg.getOffset(), msg.getLength());
ExpandedSubBlockStart.gif ContractedSubBlock.gif            switch(comm.mode)  dot.gif{
InBlock.gif                case DrawCommand.DRAW:
InBlock.gif                    if(panel != null)
InBlock.gif                        panel.drawPoint(comm);
InBlock.gif                    break;
InBlock.gif                case DrawCommand.CLEAR:
InBlock.gif                    clearPanel();
InBlock.gif                    break;
InBlock.gif                default:
InBlock.gif                    System.err.println("***** received invalid draw command " + comm.mode);
InBlock.gif                    break;
ExpandedSubBlockEnd.gif            }
ExpandedSubBlockEnd.gif        }
ExpandedSubBlockStart.gif ContractedSubBlock.gif        catch(Exception e)  dot.gif{
InBlock.gif            e.printStackTrace();
ExpandedSubBlockEnd.gif        }
ExpandedBlockEnd.gif    }

java对象实例id java对象实例化的方法_java对象实例id_06

上面兩個方法用到的兩個util類的方法

java对象实例id java对象实例化的方法_java对象实例id

java对象实例id java对象实例化的方法_java对象实例id_06

None.gif dot.gif  dot.gif
None.gif private static final ByteArrayOutputStream out_stream=new ByteArrayOutputStream(512);
None.gif dot.gif  dot.gif
ExpandedBlockStart.gif ContractedBlock.gif public static byte[] streamableToByteBuffer(Streamable obj) throws Exception  dot.gif{
InBlock.gif        byte[] result=null;
ExpandedSubBlockStart.gif ContractedSubBlock.gif        synchronized(out_stream)  dot.gif{
InBlock.gif            out_stream.reset();
InBlock.gif            DataOutputStream out=new DataOutputStream(out_stream);
InBlock.gif            obj.writeTo(out);
InBlock.gif            result=out_stream.toByteArray();
InBlock.gif            out.close();
ExpandedSubBlockEnd.gif        }
InBlock.gif        return result;
ExpandedBlockEnd.gif    }
None.gif
ExpandedBlockStart.gif ContractedBlock.gifpublic static Streamable streamableFromByteBuffer(Class cl, byte[] buffer, int offset, int length) throws Exception  dot.gif{
InBlock.gif        if(buffer == null) return null;
InBlock.gif        Streamable retval=null;
InBlock.gif        ByteArrayInputStream in_stream=new ByteArrayInputStream(buffer, offset, length);
InBlock.gif        DataInputStream in=new DataInputStream(in_stream); // changed Nov 29 2004 (bela)
InBlock.gif        retval=(Streamable)cl.newInstance();
InBlock.gif        retval.readFrom(in);
InBlock.gif        in.close();
InBlock.gif        if(retval == null)
InBlock.gif            return null;
InBlock.gif        return retval;
ExpandedBlockEnd.gif    }
None.gif dot.gif  dot.gif

就是這麼多了.
寫到這裡,突然想到,是否java默認的序列化,也就是只將實例字段進行序列化,類結構等等應該不會也序列化的.
那麼這樣,上面兩種方法實際上區別不大(第一種是我這種懶惰的人比較喜歡的,^_^).
不過默認的序列化,即使只將實例字段進行序列化,應該也要帶上字段的名稱等信息吧,這樣的話,序列後的字節數應該還是比第二種多.

補充
看了一下jdk關于ObjectOutputStream中的注釋,了解到,默認的序列化,也沒有將整個類的代碼都序列化,而是序列
化可變的數據等等,下面是jdk的一部份內容:
对象的默认序列化机制写入的内容是:对象的类,类签名,以及非瞬态和非静态字段的值。其他对象的引用(瞬态和静态字段除外)也会导致写入那些对象。可使用引用共享机制对单个对象的多个引用进行编码,这样即可将对象的图形还原为最初写入它们时的形状。

writeObject 方法负责写入特定类的对象状态,以便相应的 readObject 方法可以还原它。该方法本身不必与属于对象的超类或子类的状态有关。状态是通过使用 writeObject 方法或使用 DataOutput 支持的用于基本数据类型的方法将各个字段写入 ObjectOutputStream 来保存的。

基本数据(不包括 serializable 字段和 externalizable 数据)以块数据记录的形式写入 ObjectOutputStream 中。块数据记录由头部和数据组成。块数据部分包括标记和跟在部分后面的字节数。连续的基本写入数据被合并在一个块数据记录中。块数据记录的分块因子为 1024 字节。每个块数据记录都将填满 1024 字节,或者在终止块数据模式时被写入。调用 ObjectOutputStream 方法 writeObject、defaultWriteObject 和 writeFields 最初只是终止所有现有块数据记录。