0

正如问题所说,JVM 对实现 Marker 接口的类给予了额外的处理。例如,我使用 Serializable 对其进行了测试,如下所示:

导入java.io.*;

public class SerialazationDemo {
    public static void main(String[] args) {
        //serialized object
/*      Employee e = new Employee();
        e.name = "Reyan Ali";
        e.address = "Phokka Kuan, Ambehta Peer";
        e.SSN = 11122333;
        e.number = 101;
        try {
            FileOutputStream fileOut = new FileOutputStream("E:\\temp\\employee.ser");
            ObjectOutputStream out = new ObjectOutputStream(fileOut);
            out.writeObject(e);
            out.close();
            fileOut.close();
            System.out.printf("Serialized data is saved in /tmp/employee.ser");
        } catch (IOException i) {
            i.printStackTrace();
        }*/

        //deserialized object
         Employee e = null;
          try
          {
             FileInputStream fileIn = new FileInputStream("E:\\temp\\employee.ser");
             ObjectInputStream in = new ObjectInputStream(fileIn);
             e = (Employee) in.readObject();
             in.close();
             fileIn.close();
          }catch(IOException i)
          {
             i.printStackTrace();
             return;
          }catch(ClassNotFoundException c)
          {
             System.out.println("Employee class not found");
             c.printStackTrace();
             return;
          }
          System.out.println("Deserialized Employee...");
          System.out.println("Name: " + e.name);
          System.out.println("Address: " + e.address);
          System.out.println("SSN: " + e.SSN);
          System.out.println("Number: " + e.number);
    }
}

class Employee {
    public String name;
    public String address;
    public transient int SSN;
    public int number;

    public void mailCheck() {
        System.out.println("Mailing a check to " + name + " " + address);
    }
}

我发现 jvm 给出的异常为 java.io.NotSerializableException 但是文件是在给定的路径上创建的,类似的反序列化异常。那么为什么JVM要求它被序列化,它可以直接允许创建一个序列化。?

4

4 回答 4

4

问题说 JVM 对实现 Marker 接口的类给予了额外的处理

这个问题的正确答案是什么都没有。但这可能需要阐明,因为提问者可能使用的术语不准确。

JRE在适当的地方特别对待它们。此操作位于 Java 类库中,而不是 JVM 中。例如:

  • Object.clone()测试对象实现Cloneable.
  • ObjectOutputStream.writeObject()测试正在编写的对象实现Serializable.
  • rmic以及远程对象实现远程接口的 RMI 运行时测试的一部分,这意味着扩展的接口Remote.

这与 JVM本身无关。

我发现 jvm 给出异常为 java.io.NotSerializableException

不,你没有。你发现ObjectOutputStream.writeObject()抛出了一个异常。这不是一回事。

但是 FILES 是在给定路径上创建的

该文件是由new FileOutputStream(...),在您遇到异常之前已经执行的文件创建的。

那么为什么JVM要求它被序列化,它可以直接允许创建一个序列化。?

它没有。看上面。但是ObjectOutputStream.writeObject()确实如此,而且这样做是因为制作所有东西Serializable都有许多缺点,在您提出建议之前需要考虑这些缺点。例如,考虑您不希望的可序列化密码字段的安全风险。

于 2014-08-08T04:55:29.063 回答
0

您需要扩展Serializable(或Externalizable)的原因是为了确保您只对为序列化而设计的类进行序列化。你当然不想序列化不是为它设计的类,因为那样它们的格式会很脆弱;对类的最小更改会破坏您的反序列化。

有人可能会争辩说,同样的脆弱性也适用于标记的类Serializable,但是在将类标记为时应该考虑串行形式的稳定性Serializable(或者像 Guava 那样明确否认任何稳定性)。

于 2014-08-08T04:43:48.303 回答
0

如果对象不是Serializable其状态,则无法使用ObjectOutputStrem.

必须创建文件,因为这是使用完成的FileInputStream,并且一旦关闭流,就会有一个新文件。但是如果尝试检查文件的内容,它应该是空的,因为不可序列化状态的状态不会被保存。

于 2014-08-08T04:45:47.347 回答
0

什么是标记接口?

当一个接口被java解释器提供为句柄来标记一个类以便它可以在运行时向它提供特殊行为并且它们没有任何方法声明时,它被称为标记接口

标记接口只是将一个类标记为特定类型。

为什么需要标记接口?

标记接口用作标记,将消息通知给 java 编译器,以便它可以向实现它的类添加特殊行为。因此,如果 JVM 看到一个类是可序列化的,它会对它进行一些特殊操作

JVM 对序列化接口做了什么?

当一个类实现可序列化接口时,它向 JVM 保证该类可以在运行时提供特殊行为(序列化/反序列化)。

因此,当您尝试序列化对象时,JVM 想要确认该类型的对象类是否已签订合同(实现序列化接口)以在运行时显示此特殊行为(待序列化/反序列化)。如果已实现,则 JVM确保它可以进一步进行序列化,否则它会抛出异常,表明您正在尝试序列化不同意准备好进行序列化或反序列化的条款和条件的对象。

于 2014-08-08T05:03:33.687 回答