从零开始的java学习Day07----------基础篇(继承,抽象类,接口,多态)

继承

就是子类继承父类的属性和行为,使得子类对象具有与父类相同的属性、相同的行为。
子类可以直接访问父类中的非私有的属性和行为。
提高代码的复用性。
类与类之间产生了关系,是多态的前提。
Object类是所有类的根类,直接或者间接被所有类继承

特点

Java只支持单继承,不支持多继承
Java支持多层继承(继承体系)。

关键字

extends(定义类与类之间父子关系)

格式

class 子类名 extends 父类名 ; 在创建类时,在子类后加入关键字和父类名

示例
public class Demo extends Demo2{
    //类:Demo 继承类:Demo2
}

继承后的特点——成员变量

成员变量不重名

如果子类父类中出现不重名的成员变量,这时的访问是没有影响的

成员变量重名

如果子类父类中出现重名的成员变量,这时的访问是有影响的
子父类中出现了同名的成员变量时,在子类中需要访问父类中非私有成员变量时,需要使用super关键字,修饰父类成员变量

继承后的特点——成员方法

成员方法不重名

如果子类父类中出现不重名的成员方法,这时的调用是没有影响的。对象调用方法时,会先在子类中查找有没有对应的方法,若子类中存在就会执行子类中的方法,若子类中不存在就会执行父类中相应的方法

成员方法重名——重写(Override)(重点)

如果子类父类中出现重名的成员方法,这时的访问是一种特殊情况,叫做方法重写 (Override)。
方法重写 :子类中出现与父类一模一样的方法时(返回值类型,方法名和参数列表都要相同),会出现覆盖效果,也称为重写或者复写。声明不变,重新实现。

注意事项
  • static方法是属于类的,不能算重写(可以写一模一样,但是独立属于自己类,不会算作重写)
  • 父类的私有方法是属于他自己的,不能被重写(和static一样,可以写,但不算作重写)
  • 子类方法覆盖父类方法,必须要保证权限大于等于父类权限。(重点)
    如果子类的返回值类型不同,方法名和参数列表又相同,则既不能重写也不能重载(重载和返回值无关),编译会报错
  • private(本类中) < (default 默认)(同一个包) < protected(本类和子类) < public(当前项目中)
  • 子类方法覆盖父类方法,返回值类型、函数名和参数列表都要一模一样。
  • 调用父类构造方法的语句必须放在子类构造方法中的第一行

继承后的特点——构造方法(重点)

  • 构造方法的名字是与类名一致的。所以子类是无法继承父类构造方法的。
    但是可以使用父类的构造方法,使用super()就可以调用
  • 构造方法,在创建对象时就会执行,构造方法会初始化对象,(每个类肯定会有构造方法,就算你自己不写,系统也会生成默认空参构造方法)
  • 因为子类对象创建时,一定会先执行构造方法(要初始化成员变量),所以会默认一级一级往上执行,最终会找到Object
  • 父类空间会优先于子类对象产生(体现在子类的构造方法调用时,一定先调用父类的构造方法)
super和this的含义

super :代表父类的存储空间标识(可以理解为父亲的引用)。
this :代表当前对象的引用(谁调用就代表谁)。

抽象类

父类中的方法,被它的子类们重写,子类各自的实现都不尽相同。那么父类的方法声明和方法主体,只有声明还有意义,而方法主体则没有存在的意义了。我们把没有方法主体的方法称为抽象方法。Java语法规定,包含抽象方法的类就是抽象类(但是抽象类不一定必须包含抽象方法,比如一个空的抽象类)。

关键字

abstract

示例
public abstract class Demo {
    //这是一个抽象类
}

特点

抽象类中可以有构造方法,但是不能用来创建对象,不过可以供子类使用
抽象类不可以创建对象,只可以通过子类来创建对象。
抽象类的子类,如果是普通类(非抽象类),就必须重写抽象类中的抽象方法
抽象方法不能用private修饰

抽象类也是一个类,和普通类的区别
  1. 抽象类可以定义抽象方法
  2. 抽象类不能直接创建对象
  3. 抽象类的子类,如果是普通类(非抽象类),就必须重写抽象类中的抽象方法,如果是抽象类,就不一定要重写构造方法。

定义

抽象类:包含抽象方法的类。
抽象方法 : 没有方法体的方法(可以有返回值,有形式参数)。

抽象方法定义格式

修饰符 abstract 返回值 方法名(参数);

示例
public abstract class Demo {
    
    //fun01是一个抽象方法
    public abstract void fun01();
}

接口

  • 接口是方法的集合,里面主要就是封装了方法,一种公共规范标准
  • 一个类只能继承一个父类,但是一个类可以实现多个接口
  • 一般一个类需要扩展功能就使用实现接口(凡是共性的就使用父类,凡是要扩展的功能,就使用接口)

注意

  • 接口编译之后也会有calss文件,但要注意,他并不是类,而是一种引用数据类型,
  • 接口中不能有构造方法(不能创建对象),只能通过其实现类(子类,类似于被继承,一个实现接口的类可以看做是接口的子类(干爹))来创建接口
  • 接口中,没有静态代码块
定义格式
  • 使用interface 关键字
示例
public interface 接口名称 {
     //常量
     // 抽象方法
     // 默认方法
     // 静态方法
     // 私有方法
}
接口中的成员
  • JDK7及以前:常量 抽象方法
  • JDK8增加:默认方法和静态方法
  • JDK9增加:私有方法
接口中的常量

接口中不能定义变量,只能定义常量
接口中定义会被默认用public static final修饰(被final修饰的该变量就不可改变了,即为常量)

常量定义格式
int n=10
  • 上面伪代码代码定义了一个整形n,他前面会被默认加上public static final,也就是说n被定义为了一个常量关键字,且声明时必须被赋值,赋值后n的值后续不可被改变
  • 因为是静态,可以直接通过类名.n(常量名)来被调用,因为会被继承,用子类的类名也可以调用

接口中的抽象方法

  • 接口中定义方法会被默认添加 public abstract 在前面,即就算不加抽象方法关键字,也会被默认成为抽象方法
  • 如果接口的实现类(子类)是普通类,就必须实现接口中的所有接口方法,如果是抽象类,则不用
定义格式示例
返回值类型 方法名(参数...);    
  • 此接口会被默认加上 public abstract,当然自己主动写上也行

接口中的默认方法(JDK1.8及以后)

  • 和抽象方法不同,需要加default进行修饰
  • 可以供子类对象直接调用,可以供子类对象重写,但是重写不需要加default
定义格式示例
public default 返回值类型 方法名(参数类型...){
}

接口中的静态方法(JDK1.8及以后)

  • 和类中的静态方法有区别,只能供接口自己直接调用,子类及子类对象不能调用
定义格式示例
public static 返回值类型 方法名(参数列表){
}

接口中的私有方法(JDK1.9及以后)

  • 私有方法只能供接口中的默认方法访问。
  • 也可以加上static关键字变为:私有静态方法(这时可以供接口中的默认方法,静态方法,私有方法,私有静态方法使用)
  • 不能重写(子类写同名方法不会报错,但相当于是子类自己写的新方法,不会算作为重写)
定义格式示例
public private 返回值类型 方法名(参数列表){
}                                                //私有方法
public private static 返回值类型 方法名(参数列表){
}                                                //私有静态方法

接口和类之间的关系

  • 一个类实现单接口:按照各方法的注意事项正常使用就可以了
格式示例
//使用implements关键字,定义类时:
public class 类名 implements 接口名

一个类实现多个接口

  1. 多个接口中没有重名的抽象方法,实现类需要全部实现所有抽象方法
  2. 多个接口中有重名的抽象方法,实现类只需要实现一个抽象方法
  3. 多个接口中没有重名的默认方法,实现类就正常使用,不需要重写默认方法
  4. 多个接口中有重名的默认方法,实现类必须重写重名的默认方法,并且去掉default关键字
  5. 静态方法、私有方法跟实现类无关,正常使用
格式示例(和单接口区别就是用逗号后增加新接口名)
//使用implements 关键字,定义类时:
public class 类名 implements 接口名1,接口名2

接口和接口之间的关系

  • 接口之间可以单继承、多继承(类与类就不可以)、多层继承
定义格式示例
//使用extends关键字
public interface 接口1extends 接口2//接口1继承接口2
public interface 接口1extends 接口2名,接口3名,接口4.....//接口1继承接口2、接口3、接口4等等

注意

  • 如A接口继承了B接口,那么,A接口的实现类(子类)中,必须重写接口A和接口B的所有抽象方法,如果有多继承和多层继承,A的实现类也都要重写抽象方法。
一个类同时实现接口和继承类的优先级问题
  • 定义时,主要父类要写在前面,接口写在后面
  • 调用父类和接口的同名方法时,会优先调用父类中的方法

多态

  • 程序中,不同对象以自己的方式响应相同名称方法的能力称为多态

多态的前提

  1. 要有继承或者实现【二选一】
  2. 要有方法的重写(不重写,无意义)
  3. 要有父类的引用指向子类的对象(接口的引用指向实现类的对象)

多态的体现

其实多态就是让父类执行方法时,让其访问定义时指向子类里重写的同名方法

定义格式

伪代码示例
//父类类型 变量名 =new 子类对象
//例:
Fu f =new Zi();

访问特点

成员方法
  • 通过多态定义的成员方法,定义的时候,编译以左边为准,运行的时候以右边为准(即编译的时候左边没有这个方法即会报错,运行的时候会运行new的子类对象的方法)
  • 静态(static修饰的)方法因为不能重写,所以不适用多态,会执行原类型(左边)内的方法。
  • 成员变量无影响(照常按照定义时左边类型为准)

多态的好处和转换(默认和强转)

  • 实际开发过程中,把父类类型作为方法的形参,调用时,可以使用所有子类的类型进行赋值(此时会进行默认转换,把子类转为父类),方法调用的时候,里面调用子父类同名的方法的时候,会调用传进来的子类里的方法。提高了程序书写时的便利性(这里的形参如果类型写成Object,就可以传所有类,因为Object类默认是所有类的父类)

向上转型(子转父)

  • 向上转型是默认转型,当父类引用指向子类对象时,便是向上转型
  • 例如:Fu f =new zi() //就是一个向上转型
  • 格式:父类类型 对象名 = new 子类类型();

向下转型(父转子)

  • 向下转型是需要进行强制转换的,格式和数据类型的强制转换一样,在要被转换的对象名前面加(数据类型)
  • 例如:Zi z = (Zi) f // 这里的f是一个父类的对象
  • 格式:子类类型 对象名 =(子类类型)父类对象名
  • 强制类型一般在方法调用中适用。
  • 在一个方法中,已经定义了形参是父类类型,此时方法中又想调用一个子类A的独有方法,直接用父类的形参去调用是调用不了的(因为父类中没有),此时就需要定义一个子类A对象,用强制转换,将父类的形参强转后传给这个子类A对象,让它去调用子类中的独有方法。

注意:

上诉情况,能会发生将子类B默认转换后的父类再强转给子类A的对象,此时用子类A的对象去调用子类A的独有方法,也是不行的(编译成功,运行报错)。此时需要用到instanceof关键字。用instanceof关键字来判断下是否是我们下面要执行方法的对象(用if语句判断是否是子类A)。

instanceof关键字

  • instanceof可以用来给引用变量做类型校验
使用格式
变量名 instanceof 数据类型

例如:x instanceof dog; 设x是一个cat类型,此时返回结果就是false,如果x是dog类型,就会返回true

  • 如果变量属于该数据类型,返回true。
  • 如果变量不属于该数据类型,返回false。
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值