一道java 常见面试题,网上找到的几乎每一个 java 面试笔试题大全或集锦里都能找到这道题。java
题目以下:
问: 抽象类是否可继承实体类 (concrete class)面试
答: 抽象类是能够继承实体类,但前提是实体类必须有明确的构造函数
答案很明确,能够继承。其实从Object就是个实体类,java的API文档里,每一个抽象类的条目里都明确写着直接或间接继承自Object,因此这点是没有疑问的。
关键在于这答案里所说的“前提是实体类必须有明确的构造函数”一句,是什么意思。
通常学习者会写的简单试验代码:
class A{}abstract class B extends A{}
结果彻底正常,编译经过。彷佛和“实体类必须有明确的构造函数”彻底没有关系。
这个问题涉及到两个个基础知识:函数
1.全部的class都必须有一个构造方法,若是你没有在代码里声明构造方法,系统会自动给你生成一个公有无参的构造方法。而只要你本身声明了一个构造方法,不管有参无参,私有公有,系统就再也不帮你生成默认无参构造器了。学习
2.全部的子类构造器都要求在第一行代码中调用父类构造器,若是不写,系统默认去调用父类的无参构造器。
因此,若是把系统默认配给的方法也算进去,class A{}的代码其实是spa
class A{继承
public A(){}ip
}
B继承 A 的时候,则是文档
abstract class B extends A{io
public B(){编译
super();
}
}
要试验出这继承规则的内部状况,也很简单,在最上面那个简单试验代码里,加上个私有构造器,有参无参都行。
class A{
private A(){}
}
这个时候,如基础知识(1) 中所说,系统再也不给你默认无参构造器, B的构造器根据(2)中的规则去调用super(),却找不到A的无参构造器,因此致使abstract class B extends A{} 编译不能经过。(由于A中没有任何构造器可供子类调用,其实这个时候A只可以供内部类继承,我用的Eclipse的3.4版本会建议给B更名,可是这解决不了这个问题。)如今,你应该了解了资料给的那句语焉不详的“实体类必须有明确的构造函数”的含义:1.没写构造器的,那是拥有默认无参公有构造函数的,子类能够什么都不写,让默认构造器去调用它。这是最初那两行代码的状况。2.写了子类可访问的无参构造器的,也是同样,子类里能够什么都不写,用默认机制调用。3.写了 有参构造器却没写无参构造器的,父类里没有子类可访问的无参构造器,子类必须在子类构造器里的第一句写明,调用父类有参构造器,并把参数传进去。4.声明为final的以及全部构造器都不在子类访问权限以内的类没法继承其实只要是在类的继承中,不管抽象仍是实体,都须要符合这个规则的。在这个继承试验中随时删掉或是加上abstract的前缀,结果都没有变化。我的以为“实体类必须有明确的构造函数”一句实在是没法把这个状况表达清楚,因此广大求职者仍是写得清楚些好。我喜欢的写法是“能够继承,可是和实体类的继承同样,也要求父类可继承,而且拥有子类可访问到的构造器。”