继承(extends)

1. 父类与子类

父类也叫基类、超类  子类也叫派生类  在继承的而关系中,“子类就是一个父类“。也就是说,子类可以被当做父类来看待。例如父类是员工,子类是老师,那么我们可以说**”老师就是一个员工“**。  关系是“is - a”,例如“老师 is a 员工”

2. 继承的格式

2.1 定义父类的格式:(一个普通的类定义)

public class 父类名称{

//.....

}

2.2 定义子类的格式

public class 子类名称 extends 父类名称{

//.....

}

2.3 代码演示(老师类继承员工类)

2.3.1 Employee类

public class Employee(){

public void method(){

System.out.println("方法执行")

}

}

2.3.2 Teacher类,继承自Employee类

public class Teacher extends Employee{

//我们先不在里面添加任何东西

}

2.3.3 在main中,创建一个Teacher类的对象

public class Main {

public static void main(String[] args) {

Teacher one = new Teacher();

//Teacher类继承了Empolyee类的方法

one.method();

}

}

/*输出结果:

执行方法

*/

2.3.4 小结论

Teacher类继承了Employee类,也就继承了它的 public void method() 方法,达到了代码复用的效果,当父类有我们子类需要用的方法时,我们就不用再去重新打一次,直接可以拿来用。

3. 继承中成员变量的访问特点

3.1 成员变量之间的访问 (变量不重名的情况)

3.1.1 先创立一个父类Fu

public class Fu {

public int numFu = 10;  //关键字为public,可以直接通过(对象.变量名)访问,方便说明问题

}

3.1.2 再创立一个子类Zi

public class Zi extends Fu{

public int numZi = 20;

}

3.1.3 在main中分别建立父类和子类的对象

public class Demo02ExtendsField {

public static void main(String[] args) {

//创建父类对象

Fu fu = new Fu();

//父类只能找到自己的成员numFu,并没有找到子类的成员numZi

System.out.println(fu.numFu);

//创立一个子类对象

Zi zi = new Zi();

//子类对象既可以打印父类的成员numFu,也可以打印自己的成员numZi

//还是那句"先人不知道后人的事情,而后人知道先人的事情"

System.out.println(zi.numFu);

System.out.println(zi.numZi);

}

}

3.2 成员变量之间的访问 (变量重名的情况)

有两种情况:

直接通过对象访问成员变量: 等号左边是谁,就优先用谁,没有则向上找  间接通过成员方法访问成员变量 该方法属于谁,就优先用谁,没有则向上找

假设现在父类 Fu 和子类 Zi 都有一个变量名叫num  Fu 类 public class Fu {

public int num = 10;

public void methodFu(){

//这里打印的num,一定是本类的,不会再往下找子类的

System.out.println(num);

}

}

Zi类 public class Zi extends Fu{

public int num = 20;

public void methodZi(){

//这里打印的num,如果本类有,就优先打印本类的,如果没有再往上找

System.out.println(num);

}

}

第一种情况:直接通过对象访问成员变量

等号左边是谁,就优先用谁,没有则向上找。Fu fu = new Zi();等号的左边是父类

public class Demo02ExtendsField {

public static void main(String[] args) {

// Zi zi = new Fu(); 不能通过父类来构造子类,先人(父类)根本不知道后人(子类)长什么样子

Fu fu = new Zi(); //可以通过子类来构造父类,这时等号左边是父类

System.out.println(fu.num);  //10,打印的是父类的num

}

}

第二种情况:间接通过成员方法访问成员变量

public class Demo02ExtendsField {

public static void main(String[] args) {

Fu fu = new Fu();

Zi zi = new Zi();

//打印的是父类的num,因为该类没有继承其它类,他自己肯定有一个num,才能写出这个方法

fu.methodFu();  //父类的num 10,补充:没有fu.methodZi(), 先人不知道后人的方法

//如果子类有一个num,那就优先打印本类的,没有的话再往父类那里找

zi.methodZi();  //子类的num 20

//重点!子类用的是父类的方法打印num,这就要看这个方法属于谁,是谁定义的这个方法

//因为methodFu()这个方法是属于父类的,打印的当然就是父类的num

zi.methodFu();  //父类的num 10

}

}

4. 区分子类方法中的重名

假如有好多个num,父类有一个,子类有两个,怎么才能正确地打印想要的那个num呢?

4.1 父类 public class Fu {

public int num = 10;

}

4.2 子类 public class Zi extends Fu {

public int num = 20;

public void methodZi(){

int num = 30;

System.out.println(num);      //30, 局部变量

System.out.println(this.num); //20, 本类的成员变量

System.out.println(super.num);//10, 父类的成员变量

}

}

4.3 看看子类方法 methodZi() 能不能正确区分三个num public class Demo03Main {

public static void main(String[] args) {

Zi zi = new Zi();

zi.methodZi();  //30, 20, 10

}

}

4.4 总结:要想正确地打印想要的num,可以这样打

局部变量,上面的那个num = 30,就可以直接写本类的成员变量,上面的num = 20, 用this.成员变量名父类的成员变量,上面的num = 10, 用super.成员变量名

5. 继承中成员方法重名的问题

假如子类和父类都有一个方法叫 method() , 那怎么知道用的是哪一个呢?

5.1 父类 public class Fu {

public void method(){

System.out.println("父类重名方法执行");

}

}

5.2 子类 public class Zi extends Fu {

public void method(){

System.out.println("子类重名方法执行");

}

}

5.3 在main中调用 method() 方法 public class Demo04Main {

public static void main(String[] args) {

Fu fu1 = new Fu();

Fu fu2 = new Zi(); //通过子类来构造fu2

Zi zi = new Zi();

fu1.method(); //父类重名方法执行, 用的是父类方法

fu2.method(); //子类重名方法执行,用的是子类方法

zi.method();  //子类重名方法执行, 用的是子类方法

}

}

结论 :

创建的对象是谁,用谁的类来构造对象的,就优先用谁,如果没有就向上找。比如Fu fu2 = new Zi();,fu2是用子类来构造的,那fu2.method()就是用的子类的方法注意!无论是成员变量还是成员方法,如果没有都是向上找父类,绝对不会向下找子类的。

6. 继承方法中的覆盖重写

由 5. 继承中成员方法重名的问题,我们可以引出重写(Override)的概念

重写:在继承关系中,方法的名称一样,参数列表也一样

6.1 重写 (Override) 和 重载 (Overload) 的区别 重写:方法的名称一样,参数列表【也一样】。也叫覆盖、覆写 重载:方法的名称一样,参数列表【不一样】。  6.2 覆盖重写的注意事项 (了解)

6.2.1 必须保证父子类之间方法的名称相同,参数列表也相同,否则无法进行覆盖重写  6.2.2 注解:@Override,这个注解写在方法的前面,用来检验是不是有效的覆盖重写,例如当方法名写错了,@Override底下就会出现红色的波浪线,提示你这不是有效的覆盖重写。 public class Zi extends Fu {

@Override

public void method(){

System.out.println("子类重名方法执行");

}

}

这个注解可写可不写,但是强烈推荐把它写上去。  6.2.3 子类方法的返回值必须【小于等于】父类方法的返回值范围。java.lang.Object是所有类的公共最高父类(祖宗类),每个类都默认继承了它,例如String类就是Object的子类。下面代码会报错,是因为返回值的范围问题

6.2.3.1 父类 public class Fu {

public String method(){

System.out.println("父类重名方法执行");

}

}

6.2.3.2 子类 public class Zi extends Fu {

@Override

public Object method(){  //范围:Object > String 报错

System.out.println("子类重名方法执行");

}

}

6.2.4 子类方法的权限必须【大于等于】父类方法的权限修饰符。权限的排名:public > protected > (default) > private。备注:(default)不是关键字default,而是什么都不写,留空,例如: public class Fu{

int num; //num的访问权限是default

}

下面的代码会因为重写方法的权限问题而报错:

6.2.4.1 父类 public class Fu {

public void method(){

System.out.println("父类重名方法执行");

}

}

6.2.4.2 子类 public class Zi extends Fu {

@Override

protected void method(){  //protected < public 报错

System.out.println("子类重名方法执行");

}

}

6.3 覆盖重写实战演练 假如旧手机的功能有打电话、发短信、来电显示(显示号码) 新手机的功能有来电显示、发短信、来电显示(显示号码、显示头像、显示姓名) 可见新旧手机的打电话和发短信功能是一样的,但是新手机的来电显示功能比旧手机多了显示头像、显示姓名。 我们可以把旧手机当做父类,把新手机当做子类,新手机只需要重写旧手机的来电显示功能即可

6.3.1 旧手机是父类,名为Oldphone类 public class Oldphone {

//打电话功能

public void call(){

System.out.println("打电话");

}

//发短信功能

public void send(){

System.out.println("发短信");

}

//来电显示功能

public void show(){

System.out.println("显示号码");

}

}

6.3.2 新手机是子类,名为Newphone类 public class Newphone extends Oldphone{

@Override

public void show() {

super.show();  //不要修改原来的代码,直接通过super调用它,后面再添加新的内容

System.out.println("显示头像");

System.out.println("显示姓名");

}

}

6.3.3 在main中实验一下 public class Demo05Main {

public static void main(String[] args) {

Newphone newphone = new Newphone();

newphone.call();

newphone.send();

newphone.show();

}

}

/*输出结果:

打电话

发短信

显示号码

显示头像

显示姓名

*/

7. 继承中构造方法的访问特点

7.1 概述

子类的构造方法启动时,一定会先跑去启动父类的构造方法,等父类的构造方法执行完后,再去执行子类(本类)的构造方法。

7.2 代码说明一下7.1

7.2.1 父类(只有无参构造方法) public class Fu {

//父类的无参构造方法

public Fu(){

System.out.println("父类构造方法执行");

}

}

7.2.2 子类 public class Zi extends Fu {

//子类的无参构造方法

public Zi(){

System.out.println("子类构造方法执行");

}

}

7.2.3 在main中构造一个子类 public class Demo06Main {

public static void main(String[] args) {

Zi zi = new Zi();

}

}

/*输出结果:

父类构造方法执行

子类构造方法执行

*/

7.2.4 小总结 其实子类的构造方法中隐含了super()调用,如果子类的构造方法没有写super(),编译器会帮我们默认加上去。子类就变成 public class Zi extends Fu {

//子类的无参构造方法

public Zi(){

super();  //注意!这句必须写在第一行的位置,如果父类构造函数有参数,就是super(参数),有                   参数的调用,必须要自己写上去,不然会默认调用无参构造

System.out.println("子类构造方法执行");

}

}

8. super关键字的三种用法总结

8.1 用法1

在子类的成员方法中,访问父类的成员变量,比如:

8.1.1 父类 public class Fu {

public int num = 10;

}

8.1.2 子类 public class Zi extends Fu {

public int num = 20;

public void methodZi(){

// System.out.println(num);  这样打印的一定是本类的num

System.out.println(super.num); //打印的是父类的num

}

}

8.2 用法2

在子类的成员方法中,访问父类的成员方法,比如:

8.2.1 父类 public class Fu {

public void methodFu(){

System.out.println("父类的成员方法执行");

}

}

8.2.2 子类 public class Zi extends Fu{

public void methodZi(){

super.methodFu(); //访问父类的methodFu()方法

System.out.println("子类的成员方法执行");

}

}

在main中执行子类的方法 public class Demo07Main {

public static void main(String[] args) {

Zi zi = new Zi();

zi.methodZi();

}

}

/*输出结果:

父类的成员方法执行

子类的成员方法执行

*/

8.3 用法3

在子类的构造方法中,访问父类的构造方法。就在 7. 继承中构造方法的访问特点 中,请自行查阅。

9. this关键字的三种用法

9.1 概述

9.1.1 在本类的成员方法中,访问本类的成员变量

9.1.2 在本类的成员方法中,访问本类的另一个成员方法

9.1.3 在本类的构造方法中,访问本类的另一个构造方法

9.2 代码说明一下

public class Zi extends Fu {

private int num = 10;

public Zi(){

this(123);  //9.1.3 在本类的无参构造中调用有参构造

}

public Zi(int num){

this.num = num;

}

public void methodZi(){

System.out.println(this.num); //9.1.1 在本类的成员方法中,访问本类的成员变量

}

public void methodA(){

System.out.println("A方法");

}

public void methodB(){

this.methodA();  //9.1.2 在本类的成员方法中,访问本类的另一个成员方法

System.out.println("B方法");

9.3 注意事项

在构造方法中调用this,那这个this调用必须是该函数中的第一个语句,也是唯一的一个super和this两种在构造调用中,不能同时使用。两个都要排在第一行,我哪知道该怎么排。

10. java继承的三个特点

10.1 java语言是单继承的

一个类的直接父类只能有唯一的一个。

class A{}

class B extends A{}  正确写法

class C{}

class D extends A,C{} 错误写法,不能同时继承A和C

试想假如class A{}有一个 method() 方法,

Class C{}也有一个 method() 方法,

子类D同时继承类A和类C,那当我新建一个D类对象d后,

对象d想要调用父类的method方法,那它应该用A的 method() 还是C的 method() 呢?这就乱套了!

10.2 java语言是可以多级继承的

虽然,java语言是单继承的,一个类的直接父类只有一个,类D不能同时继承类A和类C

但是,可以让类A继承类C之后,类D再继承类A,C就是爷爷,A就是爸爸,D就是儿子

类D --> 类A --> 类C,这就叫多级继承。

10.3 java语言中,一个父类可以有多个子类

这就好比二胎政策,一个爸爸可以有多个儿子

java 继承 extends_java中的继承 (extends) 详解相关推荐

  1. Java多线程编程中Future模式的详解

    转载自 https://www.cnblogs.com/winkey4986/p/6203225.html Java多线程编程中,常用的多线程设计模式包括:Future模式.Master-Worker ...

  2. java调用项目中的文件_详解eclipse项目中.classpath文件的使用

    1 前言 在使用eclipse或者myeclipse进行java项目开发的时候,每个project(工程)下面都会有一个.classpath文件,那么这个文件究竟有什么作用? 2 作用 .classp ...

  3. java的vector_Java中 Vector的使用详解

    Vector 可实现自动增长的对象数组. java.util.vector提供了向量类(Vector)以实现类似动态数组的功能. 创建了一个向量类的对象后,可以往其中随意插入不同类的对象,即不需顾及类 ...

  4. Java去除字符串中空格的方法详解

    昨天写了一个关于Excel文件处理的脚本,在字符串匹配功能上总是出现多余不正确的匹配,debug调试之后,发现一个坑. 代码中字符串使用了replaceAll()方法,去除了所有空格(其中包括:首尾空 ...

  5. vue中Mixin和extends详解

    一.认识Mixin 目前我们使用组件化开发方式来开发应用程序,但是在不同组件之间存在一些相同的代码逻辑,此时我们希望对相同的代码逻辑 进行抽取. 在vue2和vue3中都支持使用Mixin来解决,Mi ...

  6. java 定义xml_java中web.xml定义详解

    1 定义头和根元素 部署描述符文件就像所有XML文件一样,必须以一个XML头开始.这个头声明可以使用的XML版本并给出文件的字符编码. DOCYTPE声明必须立即出现在此头之后.这个声明告诉服务器适用 ...

  7. csdn java社区_java中的io系统详解 - ilibaba的专栏 - 博客频道 - CSDN.NET

    Java 流在处理上分为字符流和字节流.字符流处理的单元为 2 个字节的 Unicode 字符,分别操作字符.字符数组或字符串,而字节流处理单元为 1 个字节,操作字节和字节数组. Java 内用 U ...

  8. java gil,Python中的GIL机制详解

    大家应该都知道,python有一个GIL(全局解释器锁),用于控制多线程的并发行为. 注:GIL不是必须的,可以通过对每个资源单独加锁的方式去掉GIL,也就是将GIL换成更细粒度的锁. GIL锁的实现 ...

  9. java 方法 void_Java中void方法的详解

    详细内容 void方法是Java中一个不可实例化的占位符,当方法用void来修饰时表示没有返回值.它有两个作用分别为对函数参数的限定以及对函数返回值的限定 学习过Java的人都知道,在Java中voi ...

最新文章

  1. cannot find package “github.com/coreos/go-systemd/journal”
  2. spark-submit --files 动态加载外部资源文件
  3. 图像非极大值抑制 Sobel 边缘实现
  4. 基于激光雷达点云的3D检测方法汇总(LiDAR only)
  5. 手把手教你写篇出彩的分析报告(万字长文):以叮咚买菜为例,看生鲜电商的春天是否已经到来?
  6. 栈的应用就进匹配_笔记
  7. anemometer mysql_MySQL慢日志简介及Anemometer工具介绍 | | For DBA
  8. kali mysql停止服务器_MySQL 的主从复制(高级篇)
  9. mysql 5.5.41 下载_MySQL 5.5.41/5.6.22 发布下载
  10. 超硬核!学霸把操作系统经典算法给敲完了!要知行合一
  11. keepalived+nginx保持高可用配置
  12. 每日一门之for循环的执行顺序
  13. 如何对一个普通的Java项目进行打包,打成jar包,idea操作
  14. Linux下安装yum源
  15. 武汉理工大学计算机专业课程表,武汉理工大学2014年春季第一周课表.xls
  16. 重点人员动态管控系统开发,公安情报研判分析平台建设
  17. Oracle执行计划
  18. 如何添加网络打印机-查看IP地址就可以
  19. notempty注解属于哪个依赖_@NotEmpty、@NotNull、@NotBlank注解解析
  20. 欠债还钱,天经地义(一)

热门文章

  1. 关于VS.NET RSACryptoServiceProvider的疑惑
  2. Nodejs Set和Map的使用
  3. Linux基础(2)--Linux常用shell命令
  4. mysql企业监控_mysql企业监控
  5. myeclipse 添加mysql数据库_myeclipse添加数据库
  6. 4007-基于邻接表的新边的增加(C++,附思路)
  7. C/C++中位运算操作符的使用
  8. java比较时间戳大小_JAVA中两个String类型的时间戳怎么样比较大小?
  9. 11-散列1 电话聊天狂人
  10. [转载] 深入理解Linux修改hostname