首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >文章中可外部性的差异

文章中可外部性的差异
EN

Stack Overflow用户
提问于 2013-03-27 10:23:26
回答 2查看 109关注 0票数 1

在一篇文章中,我研究了外部化和可外部化的概念.“Java中的内部类不能实现可扩展的接口,因为Java中的所有内部类的构造函数都会接受封装类的实例作为一个附加参数,因此不能为一个内部类设置一个no-arg构造函数。内部类只能通过实现序列化接口.来实现对象序列化。”

请告知上线是什么意思。

EN

回答 2

Stack Overflow用户

发布于 2013-03-27 12:03:53

类实现Externalizable接口的规则之一是:

“类必须有一个公共的无arg构造函数”

当您创建一个包含内部类的类并对其进行编译时,无论您是否在内部类中创建了非参数构造函数,javac本质上都会为内部类创建一个参数构造函数,该构造函数包含对内部类的.class文件中的类的引用。例如,考虑下面给出的代码:

代码语言:javascript
复制
import java.io.*;
class ExternalizationDemo
{
    public ExternalizationDemo(){System.out.println("Calling external");}
    class MyClass implements Externalizable
    {
        int i = 90;
        public MyClass()
        { 
            System.out.println("MyClass Constructor");
            i = 299;
        }
        public void writeExternal(ObjectOutput out)throws IOException
        {
            System.out.println("Write external of MyClass");
        }
        public void readExternal(ObjectInput in)throws IOException,ClassNotFoundException
        {
            System.out.println("Read external of MyClass");
        }
    }
    public static void main(String[] args) throws Exception
    {
        ExternalizationDemo demo = new ExternalizationDemo();
        ExternalizationDemo.MyClass mc = demo.new MyClass();
        ObjectOutputStream ous = new ObjectOutputStream(new FileOutputStream("Inner.ser"));
        ous.writeObject(mc);
        ous.close();
        System.out.println("Write successfull");
        ObjectInputStream oins = new ObjectInputStream(new FileInputStream("Inner.ser"));
        mc = (ExternalizationDemo.MyClass)oins.readObject();//throws java.io.InvalidClassException at this line
        System.out.println("Read the object successfully");
    }
}

对于上面的代码,javac创建ExternalizationDemo$MyClass.class来表示内部类.class文件。在使用javap分解代码时,我们得到以下一组指令:

代码语言:javascript
复制
Compiled from "ExternalizationDemo.java"
class ExternalizationDemo$MyClass extends java.lang.Object implements java.io.Ex
ternalizable{
int i;

final ExternalizationDemo this$0;

public ExternalizationDemo$MyClass(ExternalizationDemo);
  Code:
   0:   aload_0
   1:   aload_1
   2:   putfield        #1; //Field this$0:LExternalizationDemo;
   5:   aload_0
   6:   invokespecial   #2; //Method java/lang/Object."<init>":()V
   9:   aload_0
   10:  bipush  90
   12:  putfield        #3; //Field i:I
   15:  getstatic       #4; //Field java/lang/System.out:Ljava/io/PrintStream;
   18:  ldc     #5; //String MyClass Constructor
   20:  invokevirtual   #6; //Method java/io/PrintStream.println:(Ljava/lang/Str
ing;)V
   23:  aload_0
   24:  sipush  299
   27:  putfield        #3; //Field i:I
   30:  return

public void writeExternal(java.io.ObjectOutput)   throws java.io.IOException;
  Code:
   0:   getstatic       #4; //Field java/lang/System.out:Ljava/io/PrintStream;
   3:   ldc     #7; //String Write external of MyClass
   5:   invokevirtual   #6; //Method java/io/PrintStream.println:(Ljava/lang/Str
ing;)V
   8:   return

public void readExternal(java.io.ObjectInput)   throws java.io.IOException, java
.lang.ClassNotFoundException;
  Code:
   0:   getstatic       #4; //Field java/lang/System.out:Ljava/io/PrintStream;
   3:   ldc     #8; //String Read external of MyClass
   5:   invokevirtual   #6; //Method java/io/PrintStream.println:(Ljava/lang/Str
ing;)V
   8:   return

}

如上文所示,在第8行,它包含一个构造函数public ExternalizationDemo$MyClass(ExternalizationDemo);,其参数为ExternalizationDemo。它没有包含内部类的无参数构造函数。因此,在尝试将对象转换为ExternalizationDemo$MyClass时,在mc = (ExternalizationDemo.MyClass)oins.readObject();行中读取内部类的对象后,JIT不会为嵌套类找到非参数构造函数。因此,在抛出以下异常后,将中止对对象的读取:

代码语言:javascript
复制
Exception in thread "main" java.io.InvalidClassException: ExternalizationDemo$MyClass; ExternalizationDemo$MyClass; no valid constructor

我希望这能解释为什么内部类不能实现Externalizable接口。

票数 2
EN

Stack Overflow用户

发布于 2013-03-27 10:55:29

内部类构造函数有一个隐式的第一个参数--一个对其封闭类的引用,它是不可见的,它是由javac添加的。如果您对内部类字节码进行反编译,就可以看到它。因此,在内部类中不可能有无arg构造函数,这是Externalizable所需要的。不会出现编译错误。您甚至可以用writeObject编写一个可扩展的内部类的实例。但是一旦你尝试用readObject来阅读它,你就会得到类似的东西

代码语言:javascript
复制
 java.io.InvalidClassException: Test1$Test2; no valid constructor
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15656525

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档