面向对象(下)

4.1:类的继承

4.1.1:继承的概念

概念:在一个现有类的基础上去构建一个新的类,这个新类被称为子类,现有的类被称为超类父类,子类将自动拥有父类所有可继承的属性与方法。

基础语法

  1. public[修饰符] class 子类 extends 父类名{
  2. }

注意问题

  1. Java仅支持单继承,不支持多继承
  2. 多个类允许继承同一个父类
  3. 支持多层继承

4.1.2:重写父类方法

概念:子类自动继承父类公共的方法,有时候子类需要对父类方法进行修改,即重写父类方法

注意问题:子类重写,需要和父类具有相同的方法名,参数,返回类型

4.1.3:Super关键字

子类重写父类的方法后,子类对象无法直接访问父类成员变量与方法,需要使用super关键字,调用父类的变量与方法

子类调用父类的变量与方法

  1. super.成员变量
  2. super.成员方法(参数1,参数2...)

子类调用父类构造方法

  1. super(参数)

注意问题

  1. 调用父类构造方法必须位于子类构造方法第一行,尽量为父类添加无参数构造方法
  2. 当某个类定义了有参构造方法,系统将不再生成隐式无参构造方法

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关键字

用途:用于修饰类,变量,方法

被修饰后将具有以下特性:

  1. final修饰的无法被继承
  2. final修饰的方法无法被子类重写
  3. final修饰的变量(成员或局部变量):成为常量,无法二次赋值

4.3:抽象类与接口

4.3.1:抽象类

一种共同属性的抽象集合,将某些对象的共同特点抽象出来形成一个方法,具体对象再负责具体的方法实现

基本语法

  1. //定义抽象类
  2. [修饰符] abstract class 类名{
  3. //定义抽象方法
  4. [修饰符] abstract 返回值类型 方法名([方法参数]);
  5. }

注意问题

  1. 抽象类可以不包含抽象方法,但是包含抽象方法的类,必须定义为抽象类
  2. 抽象类无法被实例化,只可以被继承,由子类重写抽象方法

4.3.2:接口

所有的方法都是抽象方法,且只能存在常量。JDK1.8后可以有default默认方法与static静态方法

基本语法

  1. [修饰符] interface 接口名 [extends 父接口1,父接口2...]{
  2. //抽象方法
  3. [public] [abstract] 返回值类型 方法名([方法参数]);
  4. }

注意问题:接口中所有普通函数默认 public abstract

接口实现类:

  1. [修饰符] class 类名 [extends 父类名] interface [接口1,接口2...]{
  2. //先继承父类,再实现接口
  3. .
  4. .
  5. }

注意问题:实现类如果不是抽象类,就必须实现接口中的所有抽象方法


4.4:多态

4.4.1:多态概述

多态是指:相同引用类型变量,不同类的对象在调用同一个方法时,呈现出不同行为

多态:使用父类类型的变量引用子类对象,根据被引用子类对象的特性,程序会得到不同的运行效果。

多态性:由类的继承,方法重写,父类引用指向子类对象体现

  1. //定义父类Animal,包含shout抽象方法
  2. //定义子类cat,继承Animal,重写shout("喵喵")
  3. //定义子类dog,继承Animal,重写shout("汪汪")
  4. Animal an1 = new Cat();
  5. Animal an2 = new Dog();
  6. an1.shout();
  7. an2.shout();
  8. /** 结果:
  9. 喵喵
  10. 汪汪
  11. */

优势:解决了方法同名的问题,使程序更加灵活,增加程序可拓展性与可维护性

4.4.2:对象的类型转换

向上造(转)型:将子类对象当作父类类型使用(不需要显式声明)

注意:当执行子类对象的父类型变量,调用一个子类特有的方法时,会编译出错,只能将父类型变量强制转换成子类型

静态类型:当前变量所声明的类型

动态类型:当前变量所管理的对象类型

向下造型:父类型转换为子类型对象使用,改变静态类型,使静态类型与动态类型相同

A instanceof B:判断对象A是不是类(接口)B的实例或子类实例


4.5:内部类

Java中,允许在一个类的内部定义一个类,这样的类成为内部类,此类所在的类成为外部类

存在形式

  1. 成员内部类
  2. 局部内部类
  3. 静态内部类
  4. 匿名内部类

4.5.1:成员内部类

内部类与外部类可以互相访问对方的变量与方法

  1. class Outer{ //外部类
  2. int a;
  3. class Inner{ //内部类
  4. int b;
  5. }
  6. }

4.5.2:局部内部类

也称方法内部类,有效范围仅限于方法内部,局部内部类可以访问外部类的方法与变量,外部类却无法访问其变量与方法

4.5.3:静态内部类

使用static修饰的成员内部类

区别:可以跳过外部类直接访问静态内部类

  1. //静态内部类:跳过外部类对象,直接创建内部类对象
  2. Outer.Inner inner = new Outer.Inner();
  3. //成员内部类:需要通过外部类对象创建内部类对象
  4. Outer.Inner inner = new Outer().new Inner();

4.5.4:匿名内部类

当某方法需要一个接口类型的参数,除了传入一个接口实现类,还可以使用一个匿名内部类实现接口作为其方法参数

  1. new 父接口(){
  2. //匿名内部类实现父接口某方法
  3. }

4.6:Lambda表达式

JDK8的重要特性,针对只有一个抽象方法的接口实现;使用一个表达式 表达一个接口,Lambda会根据所需接口自动生成

4.6.1:表达式入门

三部分组成:([数据类型 参数1,2…])->{表达式主体}

  1. 参数列表(一般可以省略参数类型)
  2. ->(表达式箭牌)
  3. 表达式主体

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

  1. Error

4.7.2:异常的类型

4.7.3:try…catch与finally

4.7.4:throws

4.7.5:throw

4.7.6:自定义异常


4.8:垃圾回收