JavaSE基础知识之继承
一、概述

继承描述的是事物之间的所属关系,这种关系是: is-a 的关系。例如,图中的兔子属于食草动物,食草动物又属于动物。继承可以使多种事物之间形成一种关系体系,让父类更通用,子类更具体。
1.1 定义
继承:就是子类继承父类的属性和行为,使得子类对象具有与父类相同的属性、相同的行为。子类可以直接访问父类中的非私有的属性和行为。
1.2 好处
- 提高代码的复用性
- 继承是多态的前提
二、 子类继承父类后的特点
2.1 成员变量重名
在子类和父类没有重名的成员变量时,访问是没有任何影响的。如果存在重名,则需要通过super关键字访问父类成员变量,代码如下:
class Fu {
// Fu中的成员变量。
int num = 5;
}
class Zi extends Fu {
// Zi中的成员变量
int num = 6;
public void show() {
// 访问父类中的num
System.out.println("Fu num=" + super.num);
// 访问子类中的num
System.out.println("Zi num=" + num);
}
}
class ExtendsDemo{
public static void main(String[] args) {
// 创建子类对象
Zi z = new Zi();
// 调用子类中的show方法
z.show();
}
}
演示结果: Fu num = 5 Zi num = 6
通常Fu 类中的成员变量是非私有的,子类中可以直接访问。若Fu 类中的成员变量私有了,子类是不能直接访问的。通常编码时,我们遵循封装的原则,使用private修饰成员变量,想要访问父类的私有成员变量,可以在父类中提供公共的getXxx方法和
setXxx方法。
2.2 成员方法重名
如果子类父类中出现重名的成员方法,这时的访问是一种特殊情况,叫做方法重写 (Override)。
class Fu {
public void show() {
System.out.println("Fu show");
}
}
class Zi extends Fu {
//子类重写了父类的show方法
public void show() {
System.out.println("Zi show");
}
}
public class ExtendsDemo05 {
public static void main(String[] args) {
Zi z = new Zi();
// 子类中有show方法,只执行重写后的show方法
z.show(); // Zi show
}
}
- 子类方法覆盖父类方法,必须要保证权限大于等于父类权限。
- 子类方法覆盖父类方法,返回值类型、函数名和参数列表都要一模一样。
- 子类想要调用父类重名方法,需要添加super关键字。
值得一提的是,重写的方法带有对象参数时,方法调用的优先级为:
- 1. 先在本类中查找是否有名称和参数对应的方法,有则调用,没有则继续下一步
- 2. 然后到父类中查找是否有名称和参数对应的方法 ,有则调用,没有则继续下一步
- 3. 如果子类的父类还有父类,则在父类的父类中查找是否有名称和参数对应的方法 ,有则调用,没有则继续下一步
- 4. 如果父类已经是最顶层,还没有找到对应的方法,则将对象参数转型为父类,从最初的子类开始找名称和参数对应的方法(即重复1-3步)
代码如下:
class A {
public void show(A obj) {
System.out.println("A.show(A)");
}
public void show(C obj) {
System.out.println("A.show(C)");
}
}
class B extends A {
@Override
public void show(A obj) {
System.out.println("B.show(A)");
}
}
class C extends B {
}
class D extends C {
}
public static void main(String[] args) {
A a = new A();
B b = new B();
C c = new C();
D d = new D();
// 在 A 中存在 show(A obj),直接调用
a.show(a); // A.show(A)
// 在 A 中不存在 show(B obj),将 B 转型成其父类 A
a.show(b); // A.show(A)
// 在 B 中存在从 A 继承来的 show(C obj),直接调用
b.show(c); // A.show(C)
// 在 B 中不存在 show(D obj),但是存在从 A 继承来的 show(C obj),将 D 转型成其父类 C
b.show(d); // A.show(C)
// 引用的还是 B 对象,所以 ba 和 b 的调用结果一样
A ba = new B();
ba.show(c); // A.show(C)
ba.show(d); // A.show(C)
}
可简单的表述为:
- this.func(this)
- super.func(this)
- this.func(super)
- super.func(super)
2.3 构造方法
定义格式和作用
- 构造方法的名字是与类名一致的。所以子类是无法继承父类构造方法的。
- 构造方法的作用是初始化成员变量的。所以子类的初始化过程中,必须先执行父类的初始化动作。子类的构造方法中默认有一个 super() ,表示调用父类的构造方法,父类成员变量初始化后,才可以给子类使用。代码如下:
class Fu {
private int n;
Fu(){
System.out.println("Fu()");
}
}
class Zi extends Fu {
Zi(){
// super(),调用父类构造方法,子类构造函数不写也会在第一行默认调用父类空参构造
super();
System.out.println("Zi()");
}
}
public class ExtendsDemo{
public static void main (String args[]){
Zi zi = new Zi();
}
}
输出结果: Fu() Zi()
三、 抽象类
abstract class 类名字 {}
public abstract class Animal {
public abstract void run();
}
3.1 使用抽象类的注意事项
- 1. 抽象类不能创建对象,如果创建,编译无法通过而报错。只能创建其非抽象子类的对象。
- 2. 抽象类中,可以有构造方法,是供子类创建对象时,初始化父类成员使用的。
- 3. 抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
- 4. 抽象类的子类,必须重写抽象父类中所有的抽象方法,否则,编译无法通过而报错。除非该子类也是抽象类。
四、 接口
class 类名 implements 接口名 {
// 重写接口中抽象方法【必须】
// 重写接口中默认方法【可选】
}
interface A {
public abstract void showA();
public abstract void show();
}
interface B {
public abstract void showB();
public abstract void show();
}
public class C implements A, B {
@Override
public void showA() {
System.out.println("showA");
}
@Override
public void showB() {
System.out.println("showB");
}
@Override
public void show() {
System.out.println("show");
}
}
4.2.2 默认方法
定义多个接口:
interface A {
public default void methodA() {
}
public default void method() {
}
}
interface B {
public default void methodB() {
}
public default void method() {
}
}
定义实现类:
public class C implements A, B {
@Override
public void method() {
System.out.println("method");
}
}
4.2.3 静态方法
定义接口:
public interface LiveAble {
public static void run() {
System.out.println("跑起来~~~");
}
}
定义实现类:
public class Animal implements LiveAble {
// 无法重写静态方法
}
定义测试类:
public class InterfaceDemo {
public static void main(String[] args) {
Animal.run(); // 【错误】无法继承方法,也无法调用
LiveAble.run(); // 输出结果: 跑起来~~~
}
}
4.2.4 私有方法
摘自:黑马程序员讲义
JavaSE基础知识之继承的更多相关文章
- c++ 基础知识回顾 继承 继承的本质就是数据的copy
c++ 基础知识笔记 继承 什么是继承 继承就是子类继承父类的成员属性以及方法 继承的本质就是 数据的复制 是编译器帮我们做了很多操作 class Base { public: Base(){ cou ...
- JavaSE基础知识总结
最近回顾了一下Java的基础知识,决定写成博客梳理一遍,主要是JavaSE部分最基础的知识,适合考前突击,学后回顾,不适合作为初学材料. 简单的列个目录吧: 一.数据类型和运算符 二.流程控制与数组 ...
- JavaSE 基础知识(常识概念 + 基础语法)问答总结/面试题 —— 讲给应届生的 Java 开源知识项目
写在最前面 这个项目是从20年末就立好的 flag,经过几年的学习,回过头再去看很多知识点又有新的理解.所以趁着找实习的准备,结合以前的学习储备,创建一个主要针对应届生和初学者的 Java 开源知识项 ...
- JavaSE基础知识(5)—面向对象(5.4面向对象三大特征:封装、继承、多态)
面向对象编程具有三大特征: 封装 继承 多态 一.封装 1.好处 狭义的封装:也就是属性的封装,避免了任意赋值的危险,提高了数据的安全性! ①隐藏一个类中不需要对外提供的实现细节 ②使用者只能通过实现 ...
- java 基础知识十 继承和多态
java 基础知识十 继承和多态 继承 1.定义: 继承是指声明一些类,可以再进一步声明这些类的子类,而子类具有父类已经拥有的一些方法和属性,这跟现实中的父子关系是十分相似的,所以面向对象把这种 ...
- java基础知识总结--继承和接口
什么是继承?什么是接口?他们之间的区别和联系是什么? 什么是继承? 继承是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也可以用父类的功能.多个类中存在相同属性和行 ...
- javaSE基础知识(走向编程的门口)— 更新完毕
前言:玩儿编程最重要的一点:不要怕麻烦,感觉是在浪费时间: 能动手绝不哔哔:只要脑袋不傻,编程都是"一看就会,一练就废",开始学的时候,就算再基础的东西都建议手敲一遍 要有囫囵吞枣 ...
- C/C++基础知识总结——继承与派生
1. 类的继承与派生 1.1 派生类的定义 (1) 定义规范 class 派生类名: 继承方式 基类1名, 继承方式 基类2名... { ...派生类成员声明; }; (2) 从以上形式上看可以多继承 ...
- JavaSE基础知识(5)—面向对象(抽象类和接口)
一.抽象类 1.理解 用abstract关键字定义的类,称为抽象类用abstract关键字定义的方法,称为抽象方法意义:当设计父类时,发现该父类根本不需要创建对象,并且里面有不好描述的方法.这个时候往 ...
随机推荐
- 前端知识点回顾之重点篇——JavaScript异步机制
JavaScript异步机制 来源:https://www.cnblogs.com/zhaodongyu/p/3922961.html JavaScript是单线程异步执行的,单线程意味着代码在任务队 ...
- nfs服务共享,解决文件没有权限访问问题
最近在了解一些服务权限的设置,突然就被这个nfs服务的权限给绊住了.当你挂载上服务器上的共享目录 时,却无法访问里面的一些内容.内心满满的忧桑...经过努力奋斗几分钟终于搞明白了. 无法访问的原因:因 ...
- easyUI之progressbar进度条
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <hea ...
- handler四元素
Looper 一个线程可以产生一个Looper对象,由它来管理此线程里的MessageQueue(消息队列). 我们知道一个线程是一段可执行的代码,当可执行代码执行完成后,线程生命周期便会终止,线程就 ...
- 搞清clientHeight、offsetHeight、scrollHeight、offsetTop、scrollTop
每个HTML元素都具有clientHeight offsetHeight scrollHeight offsetTop scrollTop 这5个和元素高度.滚动.位置相关的属性,单凭单词很难搞清楚分 ...
- Git(3):分支管理
Git 分支管理 几乎每一种版本控制系统都以某种形式支持分支.使用分支意味着你可以从开发主线上分离开来,然后在不影响主线的同时继续工作. 创建分支命令 $git branch <branch n ...
- postman生成格式化时间
方法一: var moment = require('moment'); var data = moment().format(" YYYYMMDDHHmmss"); consol ...
- Linux下中文乱码
Linux下中文乱码 修改mysql配置文件,centeros下 配置文件在 /etc/my.cnf vi /etc/my.cnf 在[mysqld]段下添加 character-set-server ...
- maven 编译,测试,打包和安装工程
编译工程,使用命令mvn compile 测试工程,使用命令mvn test 测试和编译工程,使用命令mvn test-compile 打包工程,使用命令mvn package,将工程打包成jar\w ...
- 多线程基础知识---join方法
join方法的作用 thread.join()方法用于把指定的线程加入到当前线程中,把当前线程的CPU执行时间让给另一个线程.比如在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继 ...