Java 哪种设计占用更少的内存?

Java 哪种设计占用更少的内存?,java,memory,Java,Memory,如果我有一个接口In1和两个类c1、c2,它们实现In1 如果我有两个类x1,x2,它们只有自己的方法,它们的行为方式与c1,c2类似: In1 i1 = new c1(); i1 = new c2(); In1 i1 = new c1(); i1 = new c2(); 及 以上哪一项消耗更多的内存?假设实现在其他方面相同,则类实现接口是否不会显著改变运行时内存需求 特别关注您的代码 及 在第一个块中,一旦i1=new c2()运行,c1实例就不再被引用。这使得它有资格进行垃圾收集。该

如果我有一个
接口In1
和两个类
c1、c2
,它们实现
In1

如果我有两个类
x1,x2
,它们只有自己的方法
,它们的行为方式与
c1,c2
类似:

In1  i1 = new c1();
i1 = new c2();
In1  i1 = new c1();
i1 = new c2();


以上哪一项消耗更多的内存?

假设实现在其他方面相同,则类实现接口是否不会显著改变运行时内存需求

特别关注您的代码

在第一个块中,一旦i1=new c2()运行,c1实例就不再被引用。这使得它有资格进行垃圾收集。该代码块与第二个代码块不同,因为第二个代码块维护对两个已分配对象的引用

但是,如果将第一个代码块重写为

In1  i1a = new c1();
In1  i1b = new c2();
无论有无接口,您的内存需求都完全相同,因为您持有对对象的引用的时间相同

更新


如果你在期末考试中标记你的类的方法,我相信你会在内存分配上稍微节省一些,因为不需要。在中声明的方法假定实现在其他方面相同,则无论类实现接口与否,都不会显著改变运行时内存需求

特别关注您的代码

在第一个块中,一旦i1=new c2()运行,c1实例就不再被引用。这使得它有资格进行垃圾收集。该代码块与第二个代码块不同,因为第二个代码块维护对两个已分配对象的引用

但是,如果将第一个代码块重写为

In1  i1a = new c1();
In1  i1b = new c2();
无论有无接口,您的内存需求都完全相同,因为您持有对对象的引用的时间相同

更新


如果你在期末考试中标记你的类的方法,我相信你会在内存分配上稍微节省一些,因为不需要。在中声明的方法。

对于实现接口的类,
对象的内存可能会略有增加。@JiriTousek:我怀疑接口实现完全是在编译时管理的。如果类中的一个方法被标记为final,那么会减少一点内存占用,因为这样就不需要vtable了。但是,final方法不能用于接口。我将更新我的答案以反映这一点。接口实现将在运行时保留。如果不是,则运行时无法检查运行时强制转换,如
MyInterface bar=(MyInterface)foo
,并且您不能使用and。@JiriTousek:我认为这不是每个实例的开销,只是与类型相关的信息。当然,它必须被存储,但一旦同意,它很可能只是几个额外的字节。请参阅我的第一条评论:“在
对象的一侧,内存略有增加…”。可能有几个字节的恒定开销不会随着实例数的增加而增加,但不能称之为“完全相同”。对于实现接口的类来说,
对象的内存可能会略有增加。@JiriTousek:我怀疑接口实现完全是在编译时管理的。如果类中的一个方法被标记为final,那么会减少一点内存占用,因为这样就不需要vtable了。但是,final方法不能用于接口。我将更新我的答案以反映这一点。接口实现将在运行时保留。如果不是,则运行时无法检查运行时强制转换,如
MyInterface bar=(MyInterface)foo
,并且您不能使用and。@JiriTousek:我认为这不是每个实例的开销,只是与类型相关的信息。当然,它必须被存储,但一旦同意,它很可能只是几个额外的字节。请参阅我的第一条评论:“在
对象的一侧,内存略有增加…”。可能几个字节的固定开销不会随着实例的数量而增加,但不能称之为“完全相同”。除非你有10亿个这样的对象,否则这不太重要。在这种情况下,差异只占内存的一小部分。Java也在嵌入式系统中运行,在嵌入式系统中,内存可能非常有限。除非你有10亿个这样的对象,否则这不太可能有什么关系。在这种情况下,差异将是内存的一小部分。Java也在嵌入式系统中运行,在嵌入式系统中,内存可能非常有限。
In1  i1a = new c1();
In1  i1b = new c2();