问题描述
假设有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'基本上消耗更少的内存?
解决方法
不,您有两个 B 类型的对象,一个存储在类型 A 的引用中,另一个存储在类型 B 的引用中。
两个对象共享相同的内存使用大小,但是您不能从类型 A 的引用(名为 typeInterface
的引用)访问 B 的方法,即使该方法存在于被引用的对象中,除非您强制转换它。如果您强制转换引用,则限制将被删除,您可以访问 anotherMethod
。
您必须区分引用和对象。这就是你所需要的。
,我的问题是,当编译器编译代码和内存分配开始时,我们有两个对象对吗?
是的。
但是一种是类型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
(现在)所指对象的typeInterface
-ness。它只“记住”它指的是 A
某种。然而,在运行时,运行时系统总是知道一个对象的真实类型是什么,这样它才能正确实现instanceof
、类型转换、getClass()
、方法分派等等
1 - Object::getClass()
的 javadoc 声明:“返回此 Object
的运行时类”。
消耗内存的是对象实例。您的两个实例均由 new B()
创建,因此它们将占用相同数量的堆内存。
除了你的两个对象实例之外,你还有两个变量指向它们。这些存储在使用它们的方法的堆栈中。一个变量占用多少内存取决于它是原始变量还是对象引用,仅此而已。所有对象引用(无论其类型如何)在那里占用相同的空间。
,接口只是确保对象在编译时在技术上和逻辑上都满足特定标准。当执行代码并使用接口时,内存将被分配,就像您只是使用类实例化对象一样。
因此以下之间没有区别(在内存分配方面):
A typeInterface = new B();
和
B typeClass = new B();
首先是新的 B() 语句,它在堆上分配 sizeof(B)。
二、堆分配地址的赋值存放在变量test中,在栈上分配为sizeof(object *)(即IntPtr.Size,或32/64位基于硬件+OS+软件运行) ).
以下语句在“分配”中完全相同:
B typeClass = new B();
两者之间的唯一区别是可在变量“typeInterface”上调用的方法。
,类:
类是用户定义的蓝图或原型,从中创建对象。它表示一种类型的所有对象共有的一组属性或方法。通常,类声明可以按顺序包含这些组件:
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,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.