面向对象(下)
4.1:类的继承
4.1.1:继承的概念
概念:在一个现有类的基础上去构建一个新的类,这个新类被称为子类,现有的类被称为超类,父类,子类将自动拥有父类所有可继承的属性与方法。
基础语法:
public[修饰符] class 子类 extends 父类名{
}
注意问题:
- Java仅支持单继承,不支持多继承
- 多个类允许继承同一个父类
- 支持多层继承
4.1.2:重写父类方法
概念:子类自动继承父类公共的方法,有时候子类需要对父类方法进行修改,即重写父类方法
注意问题:子类重写,需要和父类具有相同的方法名,参数,返回类型
4.1.3:Super关键字
子类重写父类的方法后,子类对象无法直接访问父类成员变量与方法,需要使用super关键字,调用父类的变量与方法
子类调用父类的变量与方法:
super.成员变量
super.成员方法(参数1,参数2...)
子类调用父类构造方法:
super(参数)
注意问题:
- 调用父类构造方法必须位于子类构造方法第一行,尽量为父类添加无参数构造方法
- 当某个类定义了有参构造方法,系统将不再生成隐式无参构造方法
4.1.4:Object类
Java作为单根结构语言,提供一个Object类,所有的类默认继承Object类,Object提供了一些常用方法,用来重写函数
常用方法:
方法声明 | 功能描述 |
---|---|
boolean equals(Object obj) | 判断某个对象是否与调用此方法的对象相等 |
final Class<?> getClass() | 返回此Object运行时类 |
int hashCode() | 返回该对象哈希码值 |
String toString() | 返回该对象的字符串表示 |
void finalize() | 垃圾回收器调用此方法清理未引用的对象资源 |
4.2:final关键字
用途:用于修饰类,变量,方法
被修饰后将具有以下特性:
- final修饰的类:无法被继承
- final修饰的方法:无法被子类重写
- final修饰的变量(成员或局部变量):成为常量,无法二次赋值
4.3:抽象类与接口
4.3.1:抽象类
一种共同属性的抽象集合,将某些对象的共同特点抽象出来形成一个方法,具体对象再负责具体的方法实现
基本语法:
//定义抽象类
[修饰符] abstract class 类名{
//定义抽象方法
[修饰符] abstract 返回值类型 方法名([方法参数]);
}
注意问题:
- 抽象类可以不包含抽象方法,但是包含抽象方法的类,必须定义为抽象类
- 抽象类无法被实例化,只可以被继承,由子类重写抽象方法
4.3.2:接口
所有的方法都是抽象方法,且只能存在常量。JDK1.8后可以有default默认方法与static静态方法
基本语法:
[修饰符] interface 接口名 [extends 父接口1,父接口2...]{
//抽象方法
[public] [abstract] 返回值类型 方法名([方法参数]);
}
注意问题:接口中所有普通函数默认 public abstract
接口实现类:
[修饰符] class 类名 [extends 父类名] interface [接口1,接口2...]{
//先继承父类,再实现接口
.
.
}
注意问题:实现类如果不是抽象类,就必须实现接口中的所有抽象方法
4.4:多态
4.4.1:多态概述
多态是指:相同引用类型变量,不同类的对象在调用同一个方法时,呈现出不同行为
多态:使用父类类型的变量引用子类对象,根据被引用子类对象的特性,程序会得到不同的运行效果。
多态性:由类的继承,方法重写,父类引用指向子类对象体现
//定义父类Animal,包含shout抽象方法
//定义子类cat,继承Animal,重写shout("喵喵")
//定义子类dog,继承Animal,重写shout("汪汪")
Animal an1 = new Cat();
Animal an2 = new Dog();
an1.shout();
an2.shout();
/** 结果:
喵喵
汪汪
*/
优势:解决了方法同名的问题,使程序更加灵活,增加程序可拓展性与可维护性
4.4.2:对象的类型转换
向上造(转)型:将子类对象当作父类类型使用(不需要显式声明)
注意:当执行子类对象的父类型变量,调用一个子类特有的方法时,会编译出错,只能将父类型变量强制转换成子类型
静态类型:当前变量所声明的类型
动态类型:当前变量所管理的对象类型
向下造型:父类型转换为子类型对象使用,改变静态类型,使静态类型与动态类型相同
A instanceof B
:判断对象A是不是类(接口)B的实例或子类实例
4.5:内部类
Java中,允许在一个类的内部定义一个类,这样的类成为内部类,此类所在的类成为外部类
存在形式:
- 成员内部类
- 局部内部类
- 静态内部类
- 匿名内部类
4.5.1:成员内部类
内部类与外部类可以互相访问对方的变量与方法
class Outer{ //外部类
int a;
class Inner{ //内部类
int b;
}
}
4.5.2:局部内部类
也称方法内部类,有效范围仅限于方法内部,局部内部类可以访问外部类的方法与变量,外部类却无法访问其变量与方法
4.5.3:静态内部类
使用static修饰的成员内部类
区别:可以跳过外部类直接访问静态内部类
//静态内部类:跳过外部类对象,直接创建内部类对象
Outer.Inner inner = new Outer.Inner();
//成员内部类:需要通过外部类对象创建内部类对象
Outer.Inner inner = new Outer().new Inner();
4.5.4:匿名内部类
当某方法需要一个接口类型的参数,除了传入一个接口实现类,还可以使用一个匿名内部类实现接口作为其方法参数
new 父接口(){
//匿名内部类实现父接口某方法
}
4.6:Lambda表达式
JDK8的重要特性,针对只有一个抽象方法的接口实现;使用一个表达式 表达一个接口,Lambda会根据所需接口自动生成
4.6.1:表达式入门
三部分组成:([数据类型 参数1,2…])->{表达式主体}
- 参数列表(一般可以省略参数类型)
- ->(表达式箭牌)
- 表达式主体
4.6.2:函数式接口
Lambda局限:有且只有一个抽象方法的接口,才可以使用Lambda表达式代替匿名内部类
注解:@FunctionInterface
;标注下面的接口是一个函数式接口
4.6.3:方法引用
使用::
来引用方法与构造器,进一步简化Lambda表达式
种类 | Lambda表达式 | 引用 |
---|---|---|
类名引用普通方法 | (x,y,…)->对象名x.类方法名(y,…) | 类名::类普通方法名 |
类名引用静态方法 | (x,y,…)->类名.类静态方法名(x,y,…) | 类名::类静态方法名 |
对象名引用方法 | (x,y,…)->对象名.实例方法名(x,y,…) | 对象名::实力方法名 |
构造器引用 | (x,y,…)->new 类名(x,y,…) | 类名::new |
4.7:异常
4.7.1:什么是异常
程序运行中产生的非正常情况,Java引入异常(Exception)机制,提供大量异常类,都继承自java.lang.Throwable
类
- Error