jvm 接口和类对象内存分配之间的差异

juzqafwq  于 2022-11-07  发布在  其他
关注(0)|答案(6)|浏览(139)

假设有接口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”基本上消耗的内存少得多?

mqxuamgl

mqxuamgl1#

不,您有两个类型为B的对象,一个存储在类型为A的引用上,另一个存储在类型为B的引用上。
这两个对象共享相同的内存使用量大小,但您不能从类型A的引用(名为typeInterface的引用)访问B的方法,即使该方法存在于被引用的对象中,除非您强制转换它。如果您强制转换该引用,则限制将被删除,您可以访问anotherMethod
你必须区分引用和对象,这就是你所需要的。

pwuypxnk

pwuypxnk2#

我的问题是,当编译器编译代码,当内存分配开始时,我们有两个对象,对吗?
是的,我知道
但是一个是A型,一个是B型,......
不要啊!
两者都是B类型,表达式new B(...)创建了一个B,之后发生的事情不会改变这一点。
在第一个示例中,您将B示例的引用赋给A类型的变量。这意味着当您通过该变量 * 访问对象 * 时,您只能使用A特性(方法、字段)。
然而,对象本身 * 仍然 * 是B的示例,并且在对象的生命周期内保持这种状态,我们可以 * 证明 * 它1。

System.out.println(typeInterface.getClass().getName());

将打印“B”,而不是“A”。
我们还可以更进一步,将typeInterface转换为B,并使用B方法和字段...来证明它实际上是B
它是一个B。毫不含糊。
...这意味着'typeInterface'将只有一个方法,但'typeClass'将包含一个以上的字段和一个以上的方法。
不。不正确。这个逻辑是基于错误的假设。请参阅上文。
这两个对象分配的内存量是相同的还是“typeInterface”基本上消耗的内存少得多?
是的,它们使用相同数量的内存。它们都是B示例。请参阅上文。
理解这一点的一种方法是,当你在下面做作业时:

A typeInterface = new B();

编译器“忘记”对象的B性(现在)引用。它只“记住”它引用了某种类型的A。然而,在运行时,运行时系统 * 总是 * 知道对象的真实的类型是什么,以便它可以正确地实现instanceof、类型转换、getClass()方法调度等。
1 -Object::getClass()的javadoc声明:* “返回此Object的运行时类“*。

rt4zxlrg

rt4zxlrg3#

消耗内存的是对象示例。您的两个示例都是由new B()创建的,因此它们将占用相同数量的堆内存。
除了你的两个对象示例,你还有两个指向它们的变量。这些变量存储在使用它们的方法的堆栈中。变量占用的内存取决于它是一个原语还是一个对象引用,但仅此而已。所有对象引用(不管它们的类型如何)都占用相同的空间。

kb5ga3dv

kb5ga3dv4#

Interface只是确保对象在编译时在技术上和逻辑上都满足一定的条件。当执行代码和使用接口时,内存将被分配,就像你只是使用类示例化对象一样。

因此,在以下两种情况下(在内存分配方面)没有区别:

A typeInterface = new B();

B typeClass = new B();

首先是new B()语句,它在堆上分配sizeof(B)。
第二,堆分配的地址的赋值被存储在变量test中,其在栈上被分配为sizeof(object *)(即IntPtr.Size,或基于硬件+OS+软件运行的32/64位)。
下面的语句与“allocations”中的语句完全相同:

B typeClass = new B();

两者之间的唯一区别是可在变量“typeInterface”上调用的方法。

baubqpgj

baubqpgj5#

班级:
类别是使用者定义的蓝图或原型,对象是从其中建立的。它代表一种类型的所有对象通用的属性或方法集。一般而言,类别宣告可以包含下列元件,顺序如下:

Modifiers: A class can be public or has default access (Refer to this for details).
Class name: The name should begin with an initial letter (capitalized by convention).
Superclass(if any): The name of the class’s parent (superclass), if any, preceded by the keyword extends. A class can only extend (subclass) one parent.
Interfaces(if any): A comma-separated list of interfaces implemented by the class, if any, preceded by the keyword implements. A class can implement more than one interface.
Body: The class body surrounded by braces, { }.

构造函数用于初始化新对象。字段是提供类及其对象的状态的变量,方法用于实现类及其对象的行为。
接口:像类一样,接口可以有方法和变量,但是在接口中声明的方法默认是抽象的(只有方法签名,没有)。

Interfaces specify what a class must do and not how. It is the blueprint of the class.
An Interface is about capabilities like a Player may be an interface and any class implementing Player must be able to (or must implement) move(). So it specifies a set of methods that the class has to implement.
If a class implements an interface and does not provide method bodies for all functions specified in the interface, then the class must be declared abstract.
A Java library example is Comparator Interface. If a class implements this interface, then it can be used to sort a collection.
qfe3c7zg

qfe3c7zg6#

设为接口

interface A {
    void hello();
    void hello2();
}

我们可以立即定义函数,将接口作为参数

void function example (A i) {
    i.hello();
    i.hello2();
}

这里到底要编译什么?接口函数调用。
这是怎么可能的呢?这是可能的,因为接口类型变量包含的指向函数的指针与接口中定义的函数一样多。简言之,接口是一个包含指向函数的指针变量的结构。
现在,任何实现接口的类都可以被分配给它。通过这种分配,指向(接口的)函数的指针变量被(类的)vmtable中的函数地址“填充”。
这意味着接口变量总是看到在其中定义的函数,并且只有它们(除非强制转换为类)
例如,如果类别实作界面。

class B implements A {
  public int justAField;
  @Override
  public void hello() {
    System.out.println("Hi.");
  }
  @Override
  public void hello2() {
    System.out.println("Hi2.");
  }
  public void anotherMethod() {
    System.out.println("Another one.");
  }
}

我们可以有

example(new B());

调用i.hello(); i.hello2();触发类的相应函数(通过函数指针)

相关问题