【问题标题】:How is it possible to override final writeObject() method in Custom Serialization (Java)如何在自定义序列化(Java)中覆盖最终的 writeObject() 方法
【发布时间】:2018-09-23 23:51:49
【问题描述】:

我正在学习自定义序列化,但我不明白如何覆盖 writeObject() 和 readObject() 这两个方法,因为我知道这两个方法是最终的,而且我知道最终方法不能被覆盖.

ObjectOutputStream 中的 writeObject() 方法:

public final void writeObject(Object obj) throws IOException

并且 writeObject() 需要像这里一样被覆盖:

private void writeObject(ObjectOutputStream output) throws IOException

我知道新的 writeObject() 方法是私有的,但它是通过 Java 序列化机制使用反射调用的。但我不明白如何覆盖最终方法。

帐户类别:

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class Account implements Serializable {

    private static final long serialVersionUID = 154754873L;
    String userName = "durga";
    transient String psw = "anushka";

    private void writeObject(ObjectOutputStream output) throws IOException {

        output.defaultWriteObject();
        output.writeObject(psw);
    }

    private void readObject(ObjectInputStream input) throws IOException, ClassNotFoundException {

        input.defaultReadObject();
        psw = (String) input.readObject();
    }
}

序列化演示类:

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class SerializationDemo {

    public void serialize(Account a1, String fileName) {

        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(fileName))) {

            oos.writeObject(a1); 

        } catch (FileNotFoundException ex) {

            System.out.printf("ERROR: %s", ex);

        } catch (IOException ex) {

            System.out.printf("ERROR: %s", ex);
        }
    }

    public Account deserialize(String fileName) {

        Account a2 = null;

        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("account.ser"))) {

            a2 = (Account) ois.readObject();
        } catch (FileNotFoundException ex) {

            System.out.printf("ERROR: %s", ex);

        } catch (IOException | ClassNotFoundException ex) {

            System.out.printf("ERROR: %s", ex); 
        }

        return a2;
    }
}

SerializationApp 类:

public class SerializationApp {

    public static void main(String args[]) {

        Account a1 = new Account();

        System.out.println(a1.userName + " " + a1.psw);

        SerializationDemo demo = new SerializationDemo();

        demo.serialize(a1, "account.ser"); 

        Account a2 = demo.deserialize("account.ser");

        System.out.println(a2.userName + " " + a2.psw);
    }
}

【问题讨论】:

  • 你不能覆盖最终方法,但你甚至没有尝试过,因为writeObject(ObjectOutputStream output)writeObject(Object obj)重载,而不是覆盖
  • 为什么要覆盖ObjectOutputStream 中的writeObject?在您的班级中提供writeObjectreadObject 方法还不够吗?为什么?
  • 我知道这是为了学习,但你以后应该远离 Serializeable。它被普遍认为是坏的。几个库中有更好的实现。
  • @killjoy 当然不是“普遍认为不好”。它是 Java 中大量其他事物的基础。不要草率地概括。

标签: java serialization overriding private final


【解决方案1】:

你很困惑。

  1. ObjectOutputStream.writeObject()final,您不能覆盖它。
  2. 可用于自定义序列化的private void writeObject(ObjectOutput) 方法进入您的自己的 Serializable 类,而不是扩展ObjectOutputStream 的类。不会出现覆盖问题。

【讨论】:

  • 感谢您的回复。我想我现在明白了,这不是覆盖,私有方法 writeObject() 由 JVM 使用反射调用。
  • 实际上是由ObjectOutputStream 使用反射调用的。
【解决方案2】:

无法覆盖final 方法。

但你不需要。

自定义序列化的一种方法是提供writeObjectreadObject 方法(就像你做的那样):

private void writeObject(ObjectOutputStream out) throws IOException;
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException;

请注意,我们在这里不讨论实现或覆盖方法。

这实际上应该足够了 - 我想知道为什么你需要在 ObjectOutputStream 中覆盖 writeObject

如果您想通过继承ObjectOutputStream 来自定义序列化,您仍然可以“覆盖”对象的编写方式。为此,子类ObjectOutputStream,在子类调用super() 并覆盖writeObjectOverride。如果你调用受保护的ObjectOutputStream() 构造函数,enableOverride 标志设置为true,最终方法writeObject(你不能覆盖)委托给writeObjectOverride(可以被覆盖)。

【讨论】:

    猜你喜欢
    • 2019-01-29
    • 2019-11-19
    • 1970-01-01
    • 2012-05-04
    • 2021-07-22
    • 2015-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多