【问题标题】:Externalization with inner classes内部类的外部化
【发布时间】:2014-01-26 02:38:27
【问题描述】:

我正在阅读this 网站上关于外部化的文章,我在外部化部分的限制中找到了以下段落。

如您所知,将调用默认的公共无参数构造函数 序列化实现 Externalizable 接口的对象。 因此,内部类不能实现 Externalizable 接口 在 Java 中,因为 Java 中内部类的所有构造函数将始终 接受封闭类的实例作为前置参数 因此你不能有一个内部类的无参数构造函数。 内部类只需实现即可实现对象序列化 可序列化的接口。

我对此进行了测试,结果证明这是无效的。内部类可以没有参数构造函数,也可以实现Externalizable 接口。甚至在本地课程中尝试过。工作正常。

public class ExternalizeDemo {

    class InnerClass implements Externalizable{

        public InnerClass() {
            //default no-arg inner class constructor
        }

        @Override
        public void writeExternal(ObjectOutput out) throws IOException {
            //logic to save object state
        }

        @Override
        public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
            //logic to retrieve object state
        }
    }

    public void localClassTest(){
        class LocalClass implements Externalizable{

            public LocalClass(){
                //default no-arg local class constructor
            }

            @Override
            public void writeExternal(ObjectOutput out) throws IOException {
                //logic to save object state
            }

            @Override
            public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
                //logic to retrieve object state
            }
        }
    }

}

所以要么我遗漏了一些观点,要么文章段落不再有效(我使用的是 Java 7)。那么是哪一个呢。任何建议表示赞赏。

【问题讨论】:

  • 您是否尝试过对实例进行序列化和反序列化?
  • Protip - 避免序列化和外部化。它们很旧,几乎不再实际使用。首选外部序列化程序 - 类不应该关心自己的持久性。
  • @SotiriosDelimanolis 我没有实现刚刚编译它的方法。但是文章说我们不能在内部类中使用无参数构造函数这一事实对我来说听起来不正确。
  • 实现一个接口不能有这样的限制。我认为他们的意思是它会在运行时失败。
  • 这篇文章措辞不佳,但实际上并没有说它不会编译。它说它不能调用构造函数。当你尝试它时,你会看到。但是我不赞成这种趋势,即 StackOverflow 正在成为随机其他网站的评论网站。如果您想引用您不理解的内容,请从 Java 语言规范和 Javadoc 开始。参见Object Serialization Specification #11.1:'Externalizable 接口机制不能用于内部类。'

标签: java externalizable


【解决方案1】:

它在运行时失败...下面的向导类是 SerialiserTest 的内部类并实现 Externalizable

Wizard w = new SerialiserTest().new Wizard();
outputStream = new ByteArrayOutputStream();
objectOutputStream = new ObjectOutputStream(outputStream);
objectOutputStream.writeObject(w);
byteArrayInputStream = new ByteArrayInputStream(outputStream.toByteArray());
inputStream = new ObjectInputStream(byteArrayInputStream);
Wizard wiz = (Wizard) inputStream.readObject();

Exception in thread "main" java.io.InvalidClassException: jtk.file.ser.SerialiserTest$Wizard; no valid constructor
at java.io.ObjectStreamClass$ExceptionInfo.newInvalidClassException(ObjectStreamClass.java:150)

【讨论】:

    【解决方案2】:

    该段落意味着您不能在没有外部类实例的情况下创建内部类实例(非静态嵌套类)。

    因此,在反序列化以创建内部类的实例时,代码将需要以某种方式使用外部类的实例。

    你必须打电话

    ExternalizeDemo mainClassInstance=some initializing;
    
    mainClassInstance.new InnerClass();
    

    反序列化不会有 mainClassInstance 来创建 InnerClass 实例。

    【讨论】:

    • 这是有道理的。说 Java 中内部类的构造函数将始终接受封闭类的实例作为前置参数 有点误导。谢谢。
    • @AniketThakur 这个正确的说法没有任何误导性。
    • 我只是说它不像说所有类都隐式扩展 Object 类那么容易理解。特别是上面的陈述不适用于我认为的静态内部类。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-04-26
    • 1970-01-01
    • 1970-01-01
    • 2023-01-24
    • 2014-02-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多