import java.io.*;public class User implements Serializable {
private String name;
private transient String password;
public User(String name,String password){
this.name =name;
this.password =password;
}
public String toString(){
return name+" "+password;
}
private byte[] change(byte[] buff){
//加密数组
}
private void writeObject(ObjectOutputStream stream)throws IOException{
stream.defaultWriteObject();
stream.writeObject(change(password.getBytes()));
}
private void readObject(ObjectInputStream stream)throws IOException,ClassNotFoundException{
stream.defaultReadObject();
byte[] buff=(byte[])stream.readObject();
password=new String(change(buff));
}
public static void main(String[] args)throws Exception {
User user=new User("Tom","12345");
System.out.println("Before Serialization:"+user);
ByteArrayOutputStream buf=new ByteArrayOutputStream();

ObjectOutputStream o=new ObjectOutputStream(buf);
o.writeObject(user);

ObjectInputStream in=new ObjectInputStream(
new ByteArrayInputStream(buf.toByteArray()));
user=(User)in.readObject();
System.out.println("After Serialization:"+user);
}
}上述代码中o.writeObject(user),为什么o能调用User类中定义的方法,而且参数也不对应

解决方案 »

  1.   

    ObjectOutputStream o=new ObjectOutputStream(buf); 中ObjectOutputStream得类型是java.io.ObjectOutputStream,本身就有writeObject(Object obj) 方法,而并不是User类中得方法。
      

  2.   

    楼上说得也不是很准确,应该说ObjectOutputStream本身含有writeObejct(Obejct ojb)方法,同时也允许程序员对这个方法进行重写,所以程序中调用的writeObject()方法是重写后的方法
      

  3.   

    参数对的,user是User的实例对象,所以user可以作为Object参数传入
      

  4.   

    二楼的说错了吧,一楼的还是正确的没有调用User类中的writeObject方法,更没有进行重写
      

  5.   

    如果如一楼和五楼的两位所说,调用自己原来的writeObject方法,那他还能把密码再还原吗?好像不可以了吧
      

  6.   

    啊,对不起。是我说错了。我查了下JDK帮助文档:
    public final void writeObject(Object obj) throws IOException
    将指定的对象写入 ObjectOutputStream。对象的类、类的签名,以及类及其所有超类型的非瞬态和非静态字段的值都将被写入。可以使用 writeObject 和 readObject 方法重写类的默认序列化。由此对象引用的对象是以可变迁的方式写入的,这样,可以通过 ObjectInputStream 重新构造这些对象的完全等价的图形。 
    当 OutputStream 中出现问题或者遇到不应序列化的类时,将抛出异常。所有异常对于 OutputStream 而言都是致命的,使其处于不确定状态;并由调用者来忽略或恢复流的状态。 指定者:
    接口 ObjectOutput 中的 writeObject
    参数:
    obj - 要写入的对象 
    抛出: 
    InvalidClassException - 序列化操作使用的类出了问题。 
    NotSerializableException - 某个要序列化的对象不能实现 java.io.Serializable 接口。 
    IOException - 由底层 OutputStream 抛出的任何异常。那个可能是重写类的默认序列化吧.
      

  7.   

    各位现在还是没有解决我的疑问啊
    我查了api帮助文档,serializable序列化接口没有方法或字段,仅用于标识可序列化的语义。
    而且User类没有继承ObjectOutputStream类,
    代码中writeObject方法应该就是User类定义的方法
    现在问题是在User类中,ObjectOutputStream类对象可以调用User类中的方法吗??
      

  8.   

    LZ是程序代码看错了。仔细看的话,会发现:
    User类中writeObject()方法:
    private void writeObject(ObjectOutputStream stream)throws IOException{ 
    stream.defaultWriteObject(); 
    stream.writeObject(change(password.getBytes())); 

    与main()函数中调用的方法完全是两个不同的方法:
    o.writeObject(user);  // The param is Object
    User类中writeObject()方法传递的参数是ObjectOutputStream,而main()函数中的writeObject()传递的是OBJECT对象,是两个完全不同的参数。
    所以main()函数中调用的是ObjectOutputStream中的writeObject()方法。
      

  9.   

    同意楼上的说法,
    这个程序就是先把USER存进去,用的是ObjectOutpubStream的writeObject方法
    然后在把它读出来,用的是ObjectInputStream的readObject方法,
    这个User类里定义了两个private方法writeObjec和readObject都没有用上
      

  10.   

    楼上两位应该有看到password前的transient 
    如果正如两位所说,是调用ObjectOutputStream的writeObject方法的话,那么下面这段代码就可以注释起来了private byte[] change(byte[] buff){ 
    //加密数组 

    private void writeObject(ObjectOutputStream stream)throws IOException{ 
    stream.defaultWriteObject(); 
    stream.writeObject(change(password.getBytes())); 

    private void readObject(ObjectInputStream stream)throws IOException,ClassNotFoundException{ 
    stream.defaultReadObject(); 
    byte[] buff=(byte[])stream.readObject(); 
    password=new String(change(buff)); 
    } 那么这样的话,我调试了下,它就不能实现本程序的功能了,最后打印
    Before Serialization:Tom 12345
    After Serialization:Tom null而不去注释的话,它打印的是
    Before Serialization:Tom 12345
    After Serialization:Tom 12345显然它是调用了代码中定义的这两个方法因为我看的那本书上在这之前的一个程序就是两位所说的那样调用ObjectOutputStream自己的writeObject和readObject方法
    由于有那个关键字transient,可以成功保证密码的安全,返回null
    这段代码正是通过重定义了这两个方法又可以将密码成功返回
      

  11.   

    我用工具调试过了,的确像LZ说的
    在执行到o.writeObject(user);这句时,调用了User中的writeObject()方法
    在user=(User)in.readObject(); 这句时,调用了User中readObject()方法
    通过看API,我觉得唯一能解释的就是这句话:writeObject()可以使用 writeObject 和 readObject 方法重写类的默认序列化。所以对象引用的对象是以可变迁的方式写入的。
    程序中执行到o.writeObject(user)这句时,由于在User中对writeObject传入的参数做了重写(原本是Obejct,重写后为ObjectOutputStream),因此就执行了User.writeObject()方法。
    下面是我的猜测:
    在执行o.writeObejct(user)时,先执行了ObjectOutputStream.writeObeject()方法,然后再执行了User.writeObject()方法,因为User.writeObject()方法传入的是ObjectOutputStream引用对象,也可以说是o本身。
    不知道这样解释是否正确
      

  12.   

    虽然还没把我说服,但还是感谢conanhhy和楼上其他的朋友,由于我分少,只能给conanhhy了