title: Java学习笔记05
date: 2019-12-24 21:01:56
tags:
- Java
- 基础
- 面向对象
- 继承
- 多态
- 接口
- 抽象类
categories: Java学习笔记
继承(extends)
-
Java只支持单继承,不支持多继承。(一个儿子只能有一个爹)
-
Java支持多层继承(继承体系)
-
如果想用这个体系的所有功能用最底层的类创建对象
-
如果想看这个体系的共性功能,看最顶层的类
-
Demo:
class Animal { String color; int leg; public void eat() { System.out.println("吃饭"); } public void sleep() { System.out.println("睡觉"); } } class Cat extends Animal { //继承Animal } class Dog extends Animal { //继承Animal }
-
继承的优点:提高了代码的复用性;提高了代码的维护性;让类与类之间产生了关系,是多态的前提
-
缺点:耦合性增强
-
开发原则:高内聚,低耦合
-
耦合:类与类的关系;内聚:自己完整某件事的能力
-
继承的注意事项:
- 子类只能继承父类所有非私有的成员(成员方法和成员变量)
- 子类不能继承父类的构造方法,但是可以通过super关键字去访问父类构造方法
- 不要为了部分功能而去继承
-
继承中成员变量:
-
按照就近原则,子类中有,就不用的父类的了(但一般父类中有,子类中就不用定义了)
-
继承中的构造方法:
- 子类中所有的构造方法默认都会访问父类中空参数的构造方法
- 原因:每一个构造方法的第一条语句默认都是:
super();
Object类最顶层的父类。 - 当父类中没有无参构造方法,子类可以用
super(...)
调用父类有参构造,或者通过this(...)
调用本类的有参构造。 super(...)
和this(...)
必须写在构造方法的第一条语句上,没有的话系统默认给出
-
继承中的成员方法:
- 方法重写:子父类出现了一模一样的方法(返回值类型可以是子父类)
- 子类需要父类的功能,而功能主体子类有自己特有内容时,可以重写父类中的方法。这样,即沿袭了父类的功能,又定义了子类特有的内容。
- 沿袭父类的功能时,可以用
super.xxx
,调用父类的方法 - 注意事项:
- 父类中私有方法不能被重写
- 子类重写父类方法时,访问权限不能更低(最好是一致)
- 父类静态方法,子类也必须通过静态方法进行重写(事实上并不是重写,静态只能覆盖静态)
- 子类重写父类方法的时候,最好声明一模一样
- override(重写) & overload(重载):
- overload本类中出现的方法名一样,参数列表不同的方法。与返回值类型无关。可以改变返回值类型,只看参数列表
- override子类中出现了和父类中方法声明一模一样的方法。与返回值类型有关,返回值是一致(或者是子父类)的
-
this & super:
- this:当前对象的引用,既可以调用子类,也可以调用父类,按照就近原则,子类有就不调用父类中的
- super:当前对象父类的引用,调用父类
- 成员变量、构造方法、成员方法都可以用
-
final:
- final关键词修饰
- 修饰类,类不能被继承
- 修饰变量,变量就变成了常量,只能被赋值一次,一般会与public static一起出现
- 修饰方法,方法不能被重写
- 初始化时机:显示初始化;在对象构造完毕之前
class Demo { //final int Num = 10 //方法一 final int Num; public Demo (){ Num = 10; //方法二,在对象都早完毕之前 } }
多态(polymorphic)
-
多态的前提:
- 要有继承关系
- 要有方法重写
- 要有父类引用指向子类方法
- Demo(父类
Father
,子类Son
):
Father s = new Son(); s.XXX(); //运行的是子类的方法
-
成员变量:
- 编译看左边(父类),运行看左边(父类)
- 父类中成员变量
int Num = 10;
,子类中成员变量int Num = 20;
,执行下面代码:
Father f = new Son(); System.out.println(f.Num); //输出父类的成员变量,即10 Son s = new Son(); System.out.println(s.Num); //输出子类的成员变量,即20
- 原因:父类引用指向子类方法
-
非静态成员方法:
-
编译看左边(父类),运行看右边(子类)(动态绑定)
-
静态成员方法:
- 编译看左边(父类),运行看左边(父类)
- 静态与类相关,算不上重写,所以访问还是左边的
-
自动向上转型和强制向下转型
- 父类引用指向子类对象就是向上转型
- 强制向下转型
Son s = (Son)f; //强制将父类引用指向子类对象转为子类,这样就可以调用子类的特有方法了
-
开发的时候很少用父类引用指向子类对象,因为这样不能直接调用子类的特有方法,通常是直接创建子类对象
-
通常是当作参数的时候使用,因为扩展性强
method(new Son1());
method(new Son2()); //调用子类的xxx方法
public static void method(Father f){
f.xxx();
}
抽象类(abstract)
- 抽象类:
absttract class XXXX{}
- 抽象方法:
public abstract void xxx();
,没有实现方法 - 抽象类不一定有抽象方法,有抽象方法的类一定是抽象类或者是接口
- 抽象类不能实例化,可以用多态的方法,即父类引用指向子类对象,实现实例化
- 抽象类的子类:要么是抽象类;要么重写抽象类中的所有抽象方法
- 抽象类的成员变量:
- 既可以是变量,也可以是常量
- abstract不能修饰成员变量
- 抽象类的构造方法:
- 用于子类访问父类数据的初始化
- 抽象类的成员方法:
- 既可以是抽象的,也可以是非抽象的
- 抽象方法:强制要求子类做的事情,强制重写
- 非抽象方法:子类继承的事情,提高代码的复用性
- 一个抽象类可以没有抽象方法,这么做的目的是不让其他类创建本类对象,交给子类完成
- abstract 不能与 static、final、private关键字同时出现
接口(interface)
-
接口关键字:interface,接口中的方法都是抽象的
interface 接口名 {}
-
类实现接口用implements表示
class 类名 implements 接口名 {}
-
接口不能实例化,可以用以多态的形式,即父类引用指向子类对象,实现接口的实例化
-
接口中的成员变量:
- 只能是常量,并且是静态的、公共的
- 默认修饰符:
public static final
,三个关键字顺序任意
-
接口中的构造方法:
- 接口中没有构造方法
- 类实现接口与继承不同,implements只能算“干爹”
-
接口中的成员方法:
- 只能是抽象方法
- 默认修饰符:
public abstract
-
类 & 接口的关系:
- 类与类:继承关系,只能单继承,可以多层继承
- 类与接口:实现关系,可以单实现,也可以多实现;并且可以继承一个类实现多个接口
- 接口与接口:继承关系,可以单继承,也可以多继承(因为没有方法主体,没有安全隐患)
-
抽象类与接口设计理念:
- 抽象类:“is a”,抽象类中定义的是该继承体系的共性功能
- 接口:“like a”,接口中定义的是该继承体系的扩展功能