一道Java 常见面试题,网上找到的几乎每个 java 面试笔试题大全或集锦里都能找到这道题。
题目如下:
问: 抽象类是否可继承实体类 (concrete class)
答: 抽象类是可以继承实体类,但前提是实体类必须有明确的构造函数
答案很明确,可以继承。其实从Object就是个实体类,java的API文档里,每个抽象类的条目里都明确写着直接或间接继承自Object,所以这点是没有疑问的。
关键在于这答案里所说的“前提是实体类必须有明确的构造函数”一句,是什么意思。
一般学习者会写的简单试验代码:
class A{}
abstract class B extends A{}
结果完全正常,编译通过。似乎和“实体类必须有明确的构造函数”完全没有关系。
这个问题涉及到两个个基础知识:
1.所有的class都必须有一个构造方法,如果你没有在代码里声明构造方法,系统会自动给你生成一个公有无参的构造方法。而只要你自己声明了一个构造方法,无论有参无参,私有公有,系统就不再帮你生成默认无参构造器了。
2.所有的子类构造器都要求在第一行代码中调用父类构造器,如果不写,系统默认去调用父类的无参构造器。
所以,如果把系统默认配给的方法也算进去,class A{}的代码实际上是
class A{
public A(){}
}
B继承 A 的时候,则是
abstract class B extends A{
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的前缀,结果都没有变化。个人觉得“实体类必须有明确的构造函数”一句实在是无法把这个情况表达清楚,所以广大求职者还是写得清楚些好。
我喜欢的写法是“可以继承,但是和实体类的继承一样,也要求父类可继承,并且拥有子类可访问到的构造器。”
我笔试的时候只答的“可以继承”。心想所有的类都从Object类继承吧,掉了后半句。
相关推荐
根据给定的信息,我们可以深入探讨C++中的抽象类与继承机制。下面将详细介绍如何通过抽象类和继承在C++中实现特定的功能。 ### 概述 在这个示例中,我们有三个具体的类:`Student`、`Lecture` 和 `Module`,它们都...
抽象类是否可继承实体类 - 开心的日志 - 轻松一刻学习
抽象类不能直接创建实例,因为它们代表了一种通用的概念,而非具体的实体。 2. **抽象类的实例化**: - 抽象类不能被实例化,这意味着我们不能使用`new`关键字创建抽象类的对象。抽象类的存在是为了被其他类继承,...
抽象类和接口都可以帮助达到这一目标,但通常接口更加灵活,因为一个类可以通过实现不同的接口来承担不同的职责。 ### 四、选择建议 当面临抽象类与接口的选择时,可以根据以下几点来进行决策: 1. **是否需要多...
在这个场景中,我们将探讨如何使用C++来设计一个抽象类`Vehicle`,并从这个抽象类派生出具体的类`Car`和`Truck`。抽象类通常用于定义一个基类,它包含了一些共同的方法和属性,但不提供具体实现,而是由其子类去完成...
这意味着一个类可以从多个接口继承行为,但在Java中只能继承一个抽象类。 - **方法实现**:抽象类可以包含具体的方法实现,而接口中的方法默认都是抽象的。这一点非常重要,因为它意味着接口更倾向于定义一种协议或...
4. **继承机制**:抽象类常作为其他类的基类,通过继承抽象类,子类可以获得抽象类的所有属性和方法,并可以扩展或重写它们。 5. **接口与抽象类的区别**:在某些语言中,如Java,抽象类和接口都是用于实现多态性。...
- **抽象类继承**: 抽象类中可以定义抽象方法,子类继承后必须实现这些抽象方法。 #### 六、编码规范 **Java命名规范**: - 方法名和变量名首字母小写,其余单词首字母大写(camelCase)。 - 类名首字母大写,其余...
- 抽象类倾向于表示“is-a”关系,比如一个`Animal`抽象类可以被`Dog`和`Cat`等具体类继承。 - 接口更多地表示“can-do”关系,如`Runnable`接口,表示一个类可以执行某个任务。 6. **实现方式:** - 继承抽象类...
例如,我们可以定义一个名为`BasePageService`的抽象类,其中包含`queryByPage()`方法,用于根据条件和分页参数执行SQL查询,并返回分页结果。业务服务层的其他类可以继承这个基类,重写必要的部分以满足特定需求。 ...
3. 一个类可以继承一个抽象类,并实现多个接口。 4. 抽象类可以提供部分实现,而接口只定义行为,不提供实现。 5. 接口更强调“行为”,抽象类更倾向于“是什么”或“怎么样”。 在实际开发中,合理地使用类、抽象...
2. **继承抽象类**:如果一个类继承了抽象类,那么要么这个类也必须是抽象类,要么实现所有抽象方法。 3. **接口与抽象类的区别**:接口全由抽象方法组成,而抽象类可以包含非抽象方法。一个类可以实现多个接口,但...
- **多继承的替代**:虽然Java不支持传统的多继承(一个类继承自多个父类),但它通过接口提供了类似的功能。接口可以被多个类实现,从而实现了某种形式的多继承。 - **扩展与重写**:子类不仅可以继承父类的所有非...
6. **强制实现**:如果一个类继承自抽象类,它只需要实现抽象类中未实现的抽象方法;而如果一个类实现接口,它必须实现接口中的所有方法。 7. **构造器**:抽象类可以有构造器,用于初始化实例变量;接口不能有构造...
而使用抽象类,当需要增加新的抽象方法时,所有继承该抽象类的子类都需要进行相应的修改。 #### 总结 抽象类和接口在Java中都是重要的设计模式,它们各自有独特的特性和适用场景。正确理解和运用这两种机制对于...
在对象关系映射(ORM)框架中,实体类是对数据库表的抽象,每个实体类对应数据库中的一个表,类中的属性对应表中的字段。例如,如果有一个名为"Employees"的数据库表,那么对应的Java实体类可能是这样的: ```java ...
这样,对于每个新的实体类,我们只需要继承`BaseRepository<T>`并传入对应的DbContext即可,无需编写具体的数据库操作代码。 在实际项目中,我们还可以根据需求扩展这些万能方法,比如添加分页查询、事务处理、性能...
5. **继承与接口**:高级的实体类生成工具可能会提供基于继承的多表关联支持,比如基类包含公共属性,派生类包含特定表的属性。同时,也可能生成实现接口的类,这些接口可以用于数据访问的抽象。 6. **数据库操作**...