目录
面向对象的基本特征:继承、封装、多态
1. 基本概念
什么是面向对象编程?
找对象、创建对象、使用对象
什么是类,什么是对象?
类其实就是一个事物的抽象
对象就是一个具体的实体
2. 继承(extends)
什么是继承??
抽取共性,放到基类当中,具备相同的属性或方法
A extens B
A:子类/派生类 B:父类/基类/超类
当子类继承了父类之后,子类就拥有了父类的属性和方法。
继承的意义:代码的重复使用
在Java中,只能是单继承,不能是多继承。(可以使用接口实现类似于多继承的功能)
☠☠子类继承父类,需要先帮助父类来构造(super)
super 和 this的区别???
this() 和 super() 不能共存,都不能在static修饰的方法中使用
区别 | this | super |
---|---|---|
概念 | 访问本类中的属性和方法 | 由子类访问父类中的属性和方法 |
查找范围 | 先查找本类,如果本类没有就调用父类 | 不查找本类而直接调用父类 |
特殊 | 表示当前对象 | 无 |
final密封
final修饰类,代表当前这个类不能被继承。
3. 访问权限
- private: 类内部能访问, 类外部不能访问
- 默认(也叫包访问权限): 类内部能访问, 同一个包中的类可以访问, 其他类不能访问
- protected: 类内部能访问, 子类和同一个包中的类可以访问, 其他类不能访问
- public : 类内部和类的调用者都能访问
范围 | private | default | protected | public |
---|---|---|---|---|
同一包中的同一类 | √ | √ | √ | √ |
同一包中的不同类 | √ | √ | √ | |
不同包中的子类 | √ | √ | ||
不同包中的非子类 | √ |
4. 🎒包(package)
包 (package) 是组织类的一种方式,使用包的主要目的是保证类的唯一性。
jar包里面都是一个class字节码文件
举例:时间戳
import java.util.*;
public class Test {
public static void main(String[] args) {
Date date = new Date();
// 得到一个毫秒级别的时间戳
System.out.println(date.getTime());
}
}
但当两个包中都有Date方法时,就需要在使用时手动说明
import java.util.*;
import java.sql.*;
public class Test {
public static void main(String[] args) {
java.util.Date date = new java.util.Date();
System.out.println(date.getTime());
}
}
5. 多态
- 对于类的调用者而言,直接用,不管里面有啥子类。
- 能够降低代码的圈复杂性
- 可扩展能力强
类的实现者:
//类的实现者:
//父类
class Shape {
public void draw() {
}
}
//子类
class Cycle extends Shape {
@Override //ctrl+o重写快捷键
public void draw() {
System.out.println("画一个圆形⭕");
}
}
class Rect extends Shape {
@Override //ctrl+o重写快捷键
public void draw() {
System.out.println("画一个方片♦");
}
}
class Flower extends Shape {
@Override //ctrl+o重写方法的快捷键
public void draw() {
System.out.println("画一个小红花❀");
}
}
类的调用者:
//类的调用者
//class类文件
public class test {
//方法
public static void drawMap(Shape shape) {
shape.draw();
}
//多态便捷方法
public static void drawShape2() {
//我们创建了一个Shape对象的数组
Shape[] shape = {new Cycle(), new Rect(), new Cycle(), new Rect(), new Flower()};
for (Shape shape : shapes) {
shape.fraw();
}
}
//主函数
public static void main(String[] args) {
Cycle cycle = new Cycle();
drawMap(cycle);
//drawMap(new Cycle()); //简写
Rect rect = new Rect();
drawMap(rect);
//drawMap(new Rect()); //简写
Flower flower = new Flower();
drawMap(flower);
//drawMap(new Flower()); //简写
}
}
5.1 向上转型
Animal bird2 = new Bird("圆圆");
//父类 子类
向上转型发生的时机:
- 直接赋值
- 方法的传参
- 方法的返回值
通过父类引用,调用方法或成员变量的时候,只能调用父类自己特有的方法或者成员。
5.2 动态绑定(运行时绑定)
(在编译的时候调用的是父类的方法,但实际运行的时候调用了子类的方法)
- 向上转型 -> 父类引用 需要引用 子类对象
- 通过父类引用 来调用子类和父类的同名覆盖(重写/)方法
5.3 向下转型(不安全,很少用)
(前提是一定要发生了向上转型)
父类的对象让子类来引用(强制类型转换)
6. 抽象
既可以发生向上转型,也可以发生动态绑定,即:多态!
抽象类和抽象方法:👇
abstract class Shape {
//可以有成员变量 和 成员方法
public abstract void draw();
}
- 包含抽象方法的类,叫做抽象类。(方法和类都用abstract修饰的)
- 抽象类当中可以定义 数据成员 和 成员方法
- 抽象类不可以被实例化
- 抽象类存在最大的意义就是为了被继承
- 如果一个类继承了抽象类,那么这个类必须重写所有的抽象方法
- (抽象方法不能是final的) 【final 和 abstract 是不能共存的!】
- 抽象方法不能被private修饰
- 一个抽象类A 可以被另外一个抽象类B继承,但是如果有另外的普通类C继承了这个抽象类B,那么普通类C里面所有的抽象方法都要被重写
7. 接口
- 接口里面的方法:不能有普通方法,方法只能是抽象方法。且,接口当中的方法默认是public abstract的
- 在JDK1.8开始,接口当中的方法,可以是普通方法,但前提是:这个方法是有default修饰的
- 接口当中的方法,默认是public static final修饰的
- 接口同样不可以进行实例化
- 类和接口的关系是implements,同样,该类需要实现我们接口当中的抽象方法!
- 一个类可以使用implements实现多个接口,每个接口之间使用逗号分隔开就可以了。(多继承)
- 接口和接口之间的关系,使用extens关键字来维护。意为:扩展,即该接口扩展了原接口的功能
- 接口也可以发生向上转型和多态。只需要关注其具备的功能
compareTo
缺点:
对类的侵入性比较强
Cloneable标记接口
这个接口是一个空接口