我读过一些我们无法初始化界面的地方,例如:
interface MyInterface{};
以下代码绝对是非法的:
MyInterface m = new MyInterface();
我记得我读过的文字说:因为new
关键字用于为类成员分配内存;所以在接口的情况下,我们只有抽象函数,所以在接口中没有任何东西可以分配;因此,禁止初始化接口。
好的,这对我来说很有意义。
但是在抽象类的情况下,我们可以声明和定义抽象函数,非抽象函数以及正常变量;那么为什么我们也不允许初始化抽象类?正因为如此,我想知道抽象类中的变量何时以及如何被分配内存?
答案 0 :(得分:15)
没有对象是“只是”抽象类的实例 - 它始终是具体类的实例。否则你可以调用抽象方法......并且不会调用任何实现。
抽象类中的变量的分配方式与任何其他类的变量相同,后者恰好是正在初始化的实际类的超类 - 它们与“变量”中的变量一起生成层次结构中的其他类,基本上。
编辑:澄清一下,这是一个概念限制,与实现一样多。抽象类通常包含抽象方法,这是使其抽象化的原因。抽象方法的要点是允许调用者进行编译时检查,即使抽象类没有提供实现,该方法也会存在。 VM通过阻止“仅”抽象类的实例化来确保 实现。
现在抽象类也可以也用于防止实例化,即使没有任何抽象方法 - 基本上抽象类的基本点是不能< / em>直接实例化;只能实例化具体的子类。
答案 1 :(得分:5)
当你说“初始化”时,你真的是指两个不同的东西:分配和构建。分配是获取对象内存的过程;建筑是将物体本身带入生活的过程。
正如您所看到的,您的接口类不需要内存。但那不是重点。抽象类不能构造,因为它是......好吧,抽象。抽象类型没有对象。接口是抽象的。
想想梅赛德斯是一辆抽象的汽车。你可以买一辆梅赛德斯,但是你不能买一辆抽象的汽车 - 它没有语义意义。你可以想象的任何一辆车都必须具体。
编辑:考虑为什么一个类可能是抽象的可能是有用的:
因为它被声明为abstract class
。这使得它通过法令抽象出来,没有给出理由。
因为它有抽象的成员函数:成员函数没有实现,具体的派生类必须提供实现。
因为它被声明为interface
:这在道德上等同于“所有成员函数都是抽象的,并且没有成员对象”。 (对此有一个单独的关键字允许接口绕过单继承的限制。)
答案 2 :(得分:3)
这是抽象类的要点:成为其他类的基类。它专门设计为不实例化。
大多数抽象类都有抽象方法,不有实现。如果你实例化抽象类本身,你会如何调用这样的方法?
当您使用new
创建抽象类的子类的新实例时,也会分配基本抽象类所需的内存。
答案 3 :(得分:3)
抽象类是尚未完成的类,并且通常具有抽象成员(尽管它不是强制性的)。所以你不能实例化一个抽象类。这是由语言定义的。
答案 4 :(得分:1)
抽象类是一个被声明为abstract的类 - 它可能也可能是 不包括抽象方法。 抽象类无法实例化, 但它们可以被分类。
如果一个类包含抽象方法,那么类本身必须是 宣布抽象。
http://download.oracle.com/javase/tutorial/java/IandI/abstract.html
答案 5 :(得分:1)
抽象类不完整。他们有抽象的方法,没有实现。 如果你试图调用其中一个会发生什么?
抽象类'变量由具体实例化类位于内存中。
答案 6 :(得分:0)
当new
关键字用于extends
抽象类的类时,将分配抽象类中的变量。
因此,如果您没有扩展抽象类的类,那么它们永远不会被分配。
答案 7 :(得分:0)
当你实例化一个类时,你要为类的几个方面分配内存,包括方法的区域(它比这更重要)。抽象类没有某些方法的定义,所以我们不能把指针放到实际的方法上。
抽象类包含 - 至少部分 - 没有定义的方法。你不能打电话给那些,因为没有代码可以运行。
答案 8 :(得分:0)
也许包含一些代码的插图可能很有用。
abstract class AC{
abstract public void m();
}
class Main{
public static void main(String[] a){
AC obj = new AC();
obj.m(); /* Nothing to execute. */
}
}
所以必须禁止这种行为。
答案 9 :(得分:0)
顺便说一下,即使你的界面是空的,你也必须提供一个空的实现:
Serializable x = new Serializable(){};
抽象类也需要空的大括号。我不能想到遇到这些结构的需要。