一、继承
- 概念
- 就是子类继承父类的属性和行为,使得子类对象具有与父类相同的属性、相同的行为。子类可以直接访问父类中的非私有的属性和行为。
- 好处
- 提高代码的复用性。
- 类与类之间产生了关系,是多态的前提
- 继承特点
- Java 只支持单继承,不支持多继承。
- Java 支持多层继承 (继承体系)。
- 子类和父类是一种相对的概念。
- 顶层父类是 Object 类。所有的类默认继承 Object,作为父类。
- Java 只支持单继承,不支持多继承。
- 格式
- public class 子类名称 extends 父类名称 {...}
- 继承后的特点
- 成员变量,分两种情况
- 成员变量不重名
- 没有影响。
- 成员变量重名,创建子类对象时,访问有两种方式
- 直接通过子类对象访问成员变量
- 等号左边是谁,就优先用谁,没有则向上找。
- 间接通过成员方法访问成员变量
- 该方法属于谁,就优先用谁,没有则向上找。
- 直接通过子类对象访问成员变量
- 成员变量重名,子类中需要访问父类中非私有成员变量时
- 使用 super 关键字,类似于之前学过的 this 。
- 格式
- super.父类成员变量名
- 格式
- 使用 super 关键字,类似于之前学过的 this 。
- 成员变量不重名
- 成员方法
- 成员方法不重名
- 没有影响,子类有就执行,子类没有就去父类找。
- 成员方法重名,涉及到方法的重写
- 创建的对象是谁,就优先用谁,如果没有则向上找。
- 重写(Override)
- 概念:在继承关系当中,方法的名称一样,参数列表也一样。
- 特点:创建的是子类对象,则优先用子类方法。
- 重写注意事项
- 必须保证父子类之间方法的名称相同,参数列表也相同,
- @Override:写在方法上面,用来检测是不是有效的正确覆盖重写,这个注解就算不写,只要满足要求,也是正确的方法覆盖重写。
- 子类方法的返回值必须【小于等于】父类方法的返回值范围。
- 子类方法的权限必须【大于等于】父类方法的权限修饰符。
- public > protected > (default) > private
- ( default )不是关键字 default,而是什么都不写,留空。
- public > protected > (default) > private
- 必须保证父子类之间方法的名称相同,参数列表也相同,
- 重写(Override)与重载(Overload)
- 重写:方法的名称一样,参数列表【也一样】。覆盖、覆写。
- 重载:方法的名称一样,参数列表【不一样】。
- 成员方法不重名
- 构造方法
- 继承关系中,父子类构造方法的访问特点
- 子类构造方法当中有一个默认隐含的 “ super() ” 调用,所以一定是先调用的父类构造,后执行的子类构造。
- 子类构造可以通过 super 关键字来调用父类重载构造。
- super 的父类构造调用,必须是子类构造方法的第一个语句。不能一个子类构造调用多次 super 构造。
- 只有子类的构造方法,才能调用父类构造方法。
- 总结
- 子类必须调用父类构造方法,不写则赠送 super();写了则用写的指定的 super 调用,super 只能有一个,还必须是第一个。
- 继承关系中,父子类构造方法的访问特点
- super 关键字三种用法
- 在子类的成员方法中,访问父类的成员变量。
- 在子类的成员方法中,访问父类的成员方法。
- 在子类的构造方法中,访问父类的构造方法。
- super 关键字用来访问父类内容,而 this 关键字用来访问本类内容。用法也有三种
- 在本类的成员方法中,访问本类的成员变量。
- 在本类的成员方法中,访问本类的另一个成员方法。
- 在本类的构造方法中,访问本类的另一个构造方法。
- 第三种用法当中要注意
- this (...)调用也必须是构造方法的第一个语句,唯一一个。
- super 和 this 两种构造调用,不能同时使用。
- 第三种用法当中要注意
- 成员变量,分两种情况
二、抽象类
- 由来
- 父类中的方法,被它的子类们重写,子类各自的实现都不尽相同。那么父类的方法声明和方法主体,只有声明还有意义,而方法主体则没有存在的意义了。我们把没有方法主体的方法称为抽象方法。Java 语法规定,包含抽象方法的类就是抽象类
- 抽象方法
- 普通方法加上 abstract 关键字修饰,然后去掉大括号,直接分号结束。
- 抽象类
- 抽象方法所在的类,必须是抽象类才行。在class之前写上abstract即可。
- 如何使用抽象类和抽象方法
- 不能直接创建 new 抽象类对象。
- 必须用一个子类来继承抽象父类。
- 子类必须覆盖重写抽象父类当中所有的抽象方法。
- 子类去掉抽象方法的 abstract 关键字,然后补上方法体大括号。
- 创建子类对象进行使用。
- 注意事项
- 抽象类中,可以有构造方法,是供子类创建对象时,初始化父类成员使用的。
- 理解:子类的构造方法中,有默认的 super(),需要访问父类构造方法
- 抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
- 未包含抽象方法的抽象类,目的就是不想让调用者创建该类对象,通常用于某些特殊的类结构设计。
- 抽象类中,可以有构造方法,是供子类创建对象时,初始化父类成员使用的。
三、接口
- 概述
- 接口,是Java语言中一种引用类型,是方法的集合,如果说类的内部封装了成员变量、构造方法和成员方法,那么接口的内部主要就是封装了方法,包含抽象方法(JDK 7及以前),默认方法和静态方法(JDK 8),私有方法(JDK 9)。
- 接口定义
- 使用 interface 关键字
- 格式
- public interface 接口名称 { 接口内容 }
- 格式
- 使用 interface 关键字
- 含有抽象方法
- 使用 public abstract 关键字修饰,可以省略,没有方法体。
- 格式
- public abstract 返回值类型 方法名称 ( 参数列表 );
- 格式
- 使用 public abstract 关键字修饰,可以省略,没有方法体。
- 含有默认方法和静态方法
- 默认方法
- 使用 default 修饰,不可省略,供子类调用或者子类重写。
- 格式
- public default 返回值类型 方法名称 ( 参数列表 ) { 方法体 }
- 静态方法
-
- 使用 static 修饰,供接口直接调用。
- 格式
- public static 返回值类型 方法名称 ( 参数列表 ) { 方法体 }
-
- 默认方法
- 含有普通私有方法和私有静态方法
- 普通私有方法
- 解决多个默认方法之间重复代码问题。
- 格式
- private 返回值类型 方法名称 ( 参数列表 ) { 方法体 }
- 格式
- 解决多个默认方法之间重复代码问题。
- 私有静态方法
- 解决多个静态方法之间重复代码问题。
- 格式
- private static 返回值类型 方法名称 ( 参数列表 ) { 方法体 }
- 格式
- 解决多个静态方法之间重复代码问题。
- 普通私有方法
- 接口当中也可以定义 “成员变量” ,但是必须使用 public static final 三个关键字进行修饰。
-
- 从效果上看,这其实就是接口的【常量】
- 格式
-
- public static final 数据类型 常量名称 = 数据值 ;、
- 注意事项
-
-
- 接口当中的常量,可以省略 public static final,注意:不写也照样是这样。
- 接口当中的常量,必须进行赋值;不能不赋值。
- 接口中常量的名称,使用完全大写的字母,用下划线进行分隔。(推荐命名规则)
- 接口当中的常量,可以省略 public static final,注意:不写也照样是这样。
-
- 从效果上看,这其实就是接口的【常量】
- 接口的使用 (实现)
- 接口不能直接使用,必须有一个 “实现类” 来 “实现” 该接口。
- public class 实现类名称 implements 接口名称 { //...}
- 接口的实现类必须覆盖重写(实现)接口中所有的抽象方法。
- 实现:去掉 abstract 关键字,加上方法体大括号。
- 创建实现类的对象,进行使用。
- 注意事项
- 如果实现类并没有覆盖重写接口中所有的抽象方法,那么这个实现类自己就必须是抽象类。
- 接口不能直接使用,必须有一个 “实现类” 来 “实现” 该接口。
- 接口实现分类
- 接口的默认方法
- 可以通过接口实现类对象,直接调用。
- 可以被接口实现类进行覆盖重写。
- 接口的静态方法
- 通过接口名称,直接调用其中的静态方法。
- 不能通过接口实现类的对象来调用接口当中的静态方法。
- 接口的抽象方法
- 实现:去掉 abstract 关键字,加上方法体大括号。
- 如果实现类并没有覆盖重写接口中所有的抽象方法,那么这个实现类自己就必须是抽象类。
- 接口的普通私有方法和静态私有方法
- 普通私有方法
- 只有默认方法可以调用
- 静态私有方法
- 默认方法和静态方法可以调用。
- 普通私有方法
- 接口的默认方法
- 注意事项
- 接口是没有静态代码块或者构造方法的。
- 一个类的直接父类是唯一的,但是一个类可以同时实现多个接口。
- 如果实现类所实现的多个接口当中,存在重复的抽象方法,那么只需要覆盖重写一次即可。
- 如果实现类没有覆盖重写所有接口当中的所有抽象方法,那么实现类就必须是一个抽象类。
- 如果实现类所实现的多个接口当中,存在重复的默认方法,那么实现类一定要对冲突的默认方法进行覆盖重写。
- 一个类如果直接父类当中的方法,和接口当中的默认方法产生了冲突,优先用父类当中的方法。
四、多态
- 定义
- 是指同一行为,具有多个不同表现形式。
- 其实就是一句话:父类引用指向子类对象。
- 是指同一行为,具有多个不同表现形式。
- 格式
- 父类名称 对象名 = new 子类名称 ();
- 接口名称 对象名 = new 实现类名称 ();
- 访问成员变量
- 直接通过对象名称访问成员变量
- 看等号左边是谁,优先用谁,没有则向上找。
- 间接通过成员方法访问成员变量
- 看该方法属于谁,优先用谁,没有则向上找。
- 直接通过对象名称访问成员变量
- 访问成员方法
- 看 new 的是谁,就优先用谁,没有则向上找。
- 编译看左边,运行看右边
- 看 new 的是谁,就优先用谁,没有则向上找。
- 口诀
- 成员变量:编译看左边,运行还看左边。
- 成员方法:编译看左边,运行看右边。
- 多态的转型
- 分为向上转型和向下转型
- 向上转型:多态本身是子类类型向父类类型向上转换的过程,这个过程是默认的
- 向上转型一定是安全的,没有问题的,正确的。但是也有一个弊端
- 对象一旦向上转型为父类,那么就无法调用子类原本特有的内容。
- 解决方案:向下转型
- 向上转型一定是安全的,没有问题的,正确的。但是也有一个弊端
- 向下转型:父类类型向子类类型向下转换的过程,这个过程是强制的
- 操作方法:强制类型转换
- 向上转型:多态本身是子类类型向父类类型向上转换的过程,这个过程是默认的
- 分为向上转型和向下转型
- 如何才能知道一个父类引用的对象,本来是什么子类?
- 格式
- 对象 instanceof 类名称
- 这将会得到一个 boolean 值结果,也就是判断前面的对象能不能当做后面类型的实例。
- 格式
五、final 关键字
- 常见四种用法
- 修饰一个类
- 修饰的这个类不能有任何的子类
- 一个类如果是 final 的,那么其中所有的成员方法都无法进行覆盖重写。
- 修饰的这个类不能有任何的子类
- 修饰一个方法
- 使用 final 来修饰一个方法的时候,这个方法就是最终方法,也就是不能被覆盖重写。
- 修饰一个局部变量
- 使用 final 用来修饰局部变量,那么这个变量就不能进行更改。
- 一次赋值,终生不变
- 修饰一个成员变量
- 使用 final 关键字修饰,那么这个变量也照样是不可变。
- 由于成员变量具有默认值,所以用了 final 之后必须手动赋值,不会再给默认值了。
- 对于 final 的成员变量,要么使用直接赋值,要么通过构造方法赋值。二者选其一。
- 必须保证类当中所有重载的构造方法,都最终会对 final 的成员变量进行赋值。
- 使用 final 关键字修饰,那么这个变量也照样是不可变。
- 修饰一个类
六、权限修饰符
- 四种权限修饰符
七、内部类
- 定义
- 将一个类 A 定义在另一个类 B 里面,里面的那个类 A 就称为内部类,B 则称为外部类。
- 分类:两大类三种。
- 成员内部类
- 局部内部类(匿名内部类)
- 权限修饰符
- 外部类:public / (default)
- 成员内部类:public / protected / (default) / private
- 局部内部类:什么都不能写
- 成员内部类
- 格式
- 修饰符 class 外部类名称 {
- 修饰符 class 内部类名称 {
- // ...
- }
- // ...
- 修饰符 class 内部类名称 {
- }
- 修饰符 class 外部类名称 {
- 注意:内用外,随意访问;外用内,需要内部类对象。
- 如何使用成员内部类?有两种方式。
- 间接方式:在外部类的方法当中,使用内部类;然后main只是调用外部类的方法。
- 直接方式,公式:
- 【 外部类名称.内部类名称 对象名 = new 外部类名称 ().new 内部类名称 (); 】
- 格式
- 局部内部类
- 如果一个类是定义在一个方法内部的,那么这就是一个局部内部类。
- 格式
- 修饰符 class 外部类名称 {
- 修饰符 返回值类型 外部类方法名称(参数列表) {
- class 局部内部类名称 {
- // ...
- }
- class 局部内部类名称 {
- }
- 修饰符 返回值类型 外部类方法名称(参数列表) {
- }
- 修饰符 class 外部类名称 {
- 格式
- 局部内部类,如果希望访问所在方法的局部变量,那么这个局部变量必须是【有效 final 的】。
- 原因
- new 出来的对象在堆内存当中。
- 局部变量是跟着方法走的,在栈内存当中。
- 方法运行结束之后,立刻出栈,局部变量就会立刻消失。
- 但是 new 出来的对象会在堆当中持续存在,直到垃圾回收消失。
- 备注
- 从 Java 8+ 开始,只要局部变量事实不变,那么 final 关键字可以省略。
- 原因
- 如果一个类是定义在一个方法内部的,那么这就是一个局部内部类。
- 匿名内部类
- 如果接口的实现类(或者是父类的子类)只需要使用唯一的一次,那么这种情况下就可以省略掉该类的定义,而改为使用【匿名内部类】。
- 格式
- 接口名称 对象名 = new 接口名称() {
- // 覆盖重写所有抽象方法
- };
- 接口名称 对象名 = new 接口名称() {
- 对格式 “ new 接口名称() {...}” 进行解析
- new 代表创建对象的动作
- 接口名称就是匿名内部类需要实现哪个接口
- {...} 这才是匿名内部类的内容
- 匿名内部类注意事项
- 匿名内部类,在【创建对象】的时候,只能使用唯一一次。
- 如果希望多次创建对象,而且类的内容一样的话,那么就需要使用单独定义的实现类了。
- 匿名对象,在【调用方法】的时候,只能调用唯一一次。
- 如果希望同一个对象,调用多次方法,那么必须给对象起个名字。
- 匿名内部类是省略了【实现类/子类名称】,有对象名称;但是匿名对象是省略了【对象名称】
- 强调:匿名内部类和匿名对象不是一回事!!!
- 匿名内部类,在【创建对象】的时候,只能使用唯一一次。
八、static 关键字
- 概述
- static 可以用来修饰的成员变量和成员方法,被修饰的成员是属于类的,而不是单单是属于某个对象的。也就是说,既然属于类,就可以不靠创建对象来调用了。
- 当 static 修饰成员变量
- 该变量称为类变量。该类的每个对象都共享同一个类变量的值。任何对象都可以更改该类变量的值,但也可以在不创建该类的对象的情况下对类变量进行操作。
- 当 static 修饰成员方法
- 该方法称为静态方法。静态方法不属于对象,而是属于类的。直接就能通过类名称来使用它。
- 无论是成员变量,还是成员方法。如果有了static,都推荐使用类名称进行调用。
- 静态变量:类名称.静态变量
- 静态方法:类名称.静态方法()
- 注意事项
- 静态不能直接访问非静态。
- 因为在内存当中是【先】有的静态内容,【后】有的非静态内容。
- “先人不知道后人,但是后人知道先人。
- 静态方法当中不能用this。
- 因为 this 代表当前对象,通过谁调用的方法,谁就是当前对象。
- 静态不能直接访问非静态。
- 静态代码块
- 定义在成员位置,使用 static 修饰的代码块 { }
- 格式
- public class 类名称 {
- static {
- // 静态代码块的内容
- }
- static {
- }
- public class 类名称 {
- 特点
- 当第一次用到本类时,静态代码块执行唯一的一次。
- 静态内容总是优先于非静态,所以静态代码块比构造方法先执行。
- 静态代码块的典型用途
- 用来一次性地对静态成员变量进行赋值。
九、继承、多态、接口、权限、内部类、static 完结