假设有接口A和类B,类B实现接口;
interface A {
void hello();
}
class B implements A {
public int justAField;
@Override
public void hello() {
System.out.println("Hi.");
}
public void anotherMethod() {
System.out.println("Another one.");
}
}
假设我们有这两个对象
A typeInterface = new B();
B typeClass = new B();
我的问题是,当编译器编译代码和内存分配开始时,我们有两个对象,对吗?但一个是类型A,一个是类型B,这意味着'typeInterface'将只有一个方法,但'typeClass'将包含一个字段和一个方法。
这两个对象分配的内存量是相同的还是“typeInterface”基本上消耗的内存少得多?
6条答案
按热度按时间mqxuamgl1#
不,您有两个类型为B的对象,一个存储在类型为A的引用上,另一个存储在类型为B的引用上。
这两个对象共享相同的内存使用量大小,但您不能从类型A的引用(名为
typeInterface
的引用)访问B的方法,即使该方法存在于被引用的对象中,除非您强制转换它。如果您强制转换该引用,则限制将被删除,您可以访问anotherMethod
。你必须区分引用和对象,这就是你所需要的。
pwuypxnk2#
我的问题是,当编译器编译代码,当内存分配开始时,我们有两个对象,对吗?
是的,我知道
但是一个是
A
型,一个是B
型,......不要啊!
两者都是
B
类型,表达式new B(...)
创建了一个B
,之后发生的事情不会改变这一点。在第一个示例中,您将
B
示例的引用赋给A
类型的变量。这意味着当您通过该变量 * 访问对象 * 时,您只能使用A
特性(方法、字段)。然而,对象本身 * 仍然 * 是
B
的示例,并且在对象的生命周期内保持这种状态,我们可以 * 证明 * 它1。将打印“B”,而不是“A”。
我们还可以更进一步,将
typeInterface
转换为B
,并使用B
方法和字段...来证明它实际上是B
。它是一个
B
。毫不含糊。...这意味着'typeInterface'将只有一个方法,但'typeClass'将包含一个以上的字段和一个以上的方法。
不。不正确。这个逻辑是基于错误的假设。请参阅上文。
这两个对象分配的内存量是相同的还是“typeInterface”基本上消耗的内存少得多?
是的,它们使用相同数量的内存。它们都是
B
示例。请参阅上文。理解这一点的一种方法是,当你在下面做作业时:
编译器“忘记”对象的
B
性(现在)引用。它只“记住”它引用了某种类型的A
。然而,在运行时,运行时系统 * 总是 * 知道对象的真实的类型是什么,以便它可以正确地实现instanceof
、类型转换、getClass()
方法调度等。1 -
Object::getClass()
的javadoc声明:* “返回此Object
的运行时类“*。rt4zxlrg3#
消耗内存的是对象示例。您的两个示例都是由
new B()
创建的,因此它们将占用相同数量的堆内存。除了你的两个对象示例,你还有两个指向它们的变量。这些变量存储在使用它们的方法的堆栈中。变量占用的内存取决于它是一个原语还是一个对象引用,但仅此而已。所有对象引用(不管它们的类型如何)都占用相同的空间。
kb5ga3dv4#
Interface只是确保对象在编译时在技术上和逻辑上都满足一定的条件。当执行代码和使用接口时,内存将被分配,就像你只是使用类示例化对象一样。
因此,在以下两种情况下(在内存分配方面)没有区别:
和
首先是new B()语句,它在堆上分配sizeof(B)。
第二,堆分配的地址的赋值被存储在变量test中,其在栈上被分配为sizeof(object *)(即IntPtr.Size,或基于硬件+OS+软件运行的32/64位)。
下面的语句与“allocations”中的语句完全相同:
两者之间的唯一区别是可在变量“typeInterface”上调用的方法。
baubqpgj5#
班级:
类别是使用者定义的蓝图或原型,对象是从其中建立的。它代表一种类型的所有对象通用的属性或方法集。一般而言,类别宣告可以包含下列元件,顺序如下:
构造函数用于初始化新对象。字段是提供类及其对象的状态的变量,方法用于实现类及其对象的行为。
接口:像类一样,接口可以有方法和变量,但是在接口中声明的方法默认是抽象的(只有方法签名,没有)。
qfe3c7zg6#
设为接口
我们可以立即定义函数,将接口作为参数
这里到底要编译什么?接口函数调用。
这是怎么可能的呢?这是可能的,因为接口类型变量包含的指向函数的指针与接口中定义的函数一样多。简言之,接口是一个包含指向函数的指针变量的结构。
现在,任何实现接口的类都可以被分配给它。通过这种分配,指向(接口的)函数的指针变量被(类的)vmtable中的函数地址“填充”。
这意味着接口变量总是看到在其中定义的函数,并且只有它们(除非强制转换为类)
例如,如果类别实作界面。
我们可以有
调用
i.hello(); i.hello2();
触发类的相应函数(通过函数指针)