Java 面向对象3
多态
- 基本概念
- 同一种行为,在不同的对象上,会产生不同的显示结果。
- 允许不同类的对象对同一消息做出不同的响应
- 编译时多态
- 设计时多态 方法重载
- 运行时多态(通常说的这个)
- 程序运行时动态决定调用哪个方法
- 必要条件
- 满足继承关系
- 父类引用指向子类对象
- 使用
- 父类引用子类实例
- 向上转型、隐式转型、自动转型
- 父类引用指向子类实例,可以调用子类重写父类的方法以及父类派生的方法,无法调用子类独有方法。
- 小类转型大类
- 父类 static 方法,不允许子类重写
- 向上转型后,只能调用到父类原有的静态方法
- 子类引用指向父类实例
- 向下转型、强制类型转换
- 子类引用指向父类对象,此时必须进行强转,可以调用子类独有方法
- 必须满足转换条件才能进行强转
- 对象 instanceof 类
- 判断对象是否是类的实例
1
2Animal one = new Cat();
Cat temp = (Cat)one
- 父类引用子类实例
- 抽象类(abstract)
- Java 中使用抽象类,限制实例化
- 通过 abstract 修饰的类,就是抽象类
- 不允许实例化,可以通过向上转型,指向子类实例
- 通过abstract 修饰的方法,就是抽象方法
- public abstract void eat();
- 子类必须实现这个方法!
- 应用场景
- 某个父类只是知道其子类应该包含怎样的方法,但无法准确知道这些子类如何实现这些方法。
- 避免设计随意性,无意义父类实例化
- 使用规则
- 1、abstract 定义抽象类
- 2、抽象类不能直接实例化,只能被继承,可以通过向上转型完成对象实例
- 3、abstract 定义抽象方法,不需要具体实现
- 4、包含抽象方法的类是抽象类
- 5、抽象类中可以没有抽象方法
- 6、static final private 不能与 abstract 并存
- Java 中使用抽象类,限制实例化
- 接口(interface)
- 基本概念
- 接口定义了某一批类所需要遵守的规范
- 接口不关心这些类的内部数据,也不关心这些类里的方法的实现细节,它只规定这些类里必须提供某些方法
- 语法:
- [修饰符] interface 接口名 [extends 付接口1, 父接口2…]
1
2
3
4
5
6{
零个到多个常量定义...
零个到多个抽象方法定义...
零个到多个默认方法的定义.... (jdk1.8新增)
零个到多个静态方法的定义... (jdk 1.8新增)
}
- [修饰符] interface 接口名 [extends 付接口1, 父接口2…]
- 使用注意:
- 一个类可以实现多个接口,通过逗号分割。 implements
- 接口的实现要放在继承后面,一个类只能继承唯一父类,但可以实现若干个接口。实现接口的时候要去重写接口待重写的方法。否则通过 abstract 定义抽象类
- 接口也可以实现继承关系,并且可以继承多个父接口,用逗号分开
- 如果继承多个接口有多个重名的方法,子类不知道该实现哪个接口的方法,可以重写重名的方法。
- 如果继承父类的同时,也继承方法。它们都有同名的方法,默认继承父类方法。
- 代码示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25package com.zzz.tel;
// 接口访问修饰符:public 默认
public interface INet {
/*接口中抽象方法可以不写abstract关键字
/*访问修饰符默认public
* 当类实现接口时,需要去实现接口中的所有抽象方法,否则需要将该类设置为抽象类
*/
void network();
//接口中可以包含常量,默认public static final
int TEMP=20;
//default:默认方法 可以带方法体 jdk1.8后新增
//可以在实现类中重写,并可以通过接口的引用调用
default void connection(){
System.out.println("我是接口中的默认链接");
}
//static:静态方法 可以带方法体 jdk1.8后新增
//不可以在实现类中重写,可以同接口名调用
static void stop(){
System.out.println("我是接口中的静态方法");
}
}
- 基本概念
- 内部类
- 在 Java 中,可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类。
- 与之对应,包含内部类的类被称为外部类
- 内部类隐藏在外部类之内,更好的实现了信息的隐藏。不允许其它类随意的访问。
- 内部类分类
- 1、成员内部类
- 内部类中最常见的就是成员内部类,也称普通内部类
- 1、内部类在外部使用时,无法直接实例化,需要借由外部类的信息才能完成实例化
- 2、内部类的访问修饰符,可以任意,但是访问范围会受到影响
- 3、内部类可以直接访问外部类的成员,如果出现同名属性,优先访问内部类中定义的
- 4、可以使用 外部类.this.成员 的方式,访问外部类中同名的信息
- 5、外部类访问内部类信息,需要通过内部类实例,无法直接访问
- 6、内部类编译后 .class 文件命名:外部类$内部类.class
- 内部类的获取方式
- 1、new 外部类.new 内部类
- 2、外部类对象.new 内部类
- 3、外部类对象.获取方法
- 2、静态内部类
- 【成员共享】静态内部类对象可以不依赖于外部类对象,直接创建
- 1、静态内部类中,只能直接访问外部类的静态成员,如果需要调用非静态成员,可以通过对象实例
- 2、静态内部类对象实例时,可以不依赖于外部类对象
- 3、可以通过 外部类.内部类.静态成员 的方式,访问内部类中的静态成员
- 4、当内部类属性与外部类属性同名时,默认直接调用内部类中的成员;如果需要访问外部类中的静态属性,则可以通过 外部类.属性 的方式;如果需要访问外部类中的非静态属性,则可以通过 new 外部类().属性 的方式;
- 3、方法内部类
- 定义在外部类方法中的内部类,也称局部类。
- 1、定义在方法内,作用范围也在方法内
- 2、和方法内部成员使用规则一样,class 前面不可以添加 public、private、protected、static
- 3、类中不能包含静态成员
- 4、类中可以包含 final、abstract 修饰的成员
- 4、匿名内部类
- 将类的定义与类的创建,放到一起完成
- 1、匿名内部类没有类型名称、实例对象名称
- 2、编译后的文件命名:外部类$数字.class
- 3、无法使用 private、public、protected、abstract、static 修饰
- 4、无法编写构造方法,可以添加代码块
- 5、不能出现静态成员
- 6、匿名内部类可以实现接口也可以继承父类,但是不可兼得
- 适用场景
- 1、只有到类的一个实例
- 2、类在定义后马上用到
- 3、给类命名并不会导致代码更容易被理解
- 1、成员内部类