抽象类
抽象类概念
并不是所有类都用来描述具体对象
如果一个类没有足够信息描述具体对象,就是抽象类- 例子:
a)图形Shape,所有图形都有绘制draw(),
但是单纯 “图形” 不是具体图形,没法实现draw();
b)动物Animal,动物都会叫bark(),
但普通动物无法实现叫声,只有狗、猫这种具体动物才有实现- 抽象方法:没有方法体、abstract修饰的方法
抽象类:包含抽象方法的类,必须用abstract修饰抽象类语法
// 抽象类:被abstract修饰 public abstract class Shape { // 抽象方法:abstract修饰,没有{}方法体 abstract public void draw(); abstract void calcArea(); // 抽象类里可以有普通成员方法、成员变量 public double getArea(){ return area; } protected double area; }- 重点:抽象类本质还是类,可以有普通方法、属性、构造方法
抽象类特性
抽象类不能直接 new 实例化对象
Shape shape=new Shape(); //编译报错,抽象类不能new实例
- 抽象方法不能用 private 修饰
1)抽象方法必须被子类重写,private私有,子类不可见,冲突
2)abstract class Shape { abstract private void draw(); //非法修饰符,编译报错 }- 抽象方法不能被 final、static 修饰
1)final:方法不能被重写;抽象方法必须子类重写,冲突
2)static:属于类,不需要对象调用;抽象方法需要子类对象实现,冲突
3)public abstract class Shape { abstract final void methodA(); //错误 abstract public static void methodB(); //错误 }- 抽象类必须被继承
1)子类必须重写全部抽象方法,否则子类也要声明为 abstract 抽象类
2)//矩形子类,继承Shape,重写所有抽象方法,普通类 public class Rect extends Shape { private double length; private double width; Rect(double length, double width){ this.length = length; this.width = width; } @Override public void draw(){ System.out.println("矩形:length="+length+" width= "+ width); } @Override public void calcArea(){ area = length * width; } }
3)如果子类不重写父类全部抽象方法→子类必须加abstract变成抽象类- 抽象类不一定包含抽象方法;但是只要类里面有抽象方法,这个类一定是抽象类
- 抽象类可以有构造方法
1)抽象类不能自己 new 对象,但是子类创建对象时,会调用父抽象类构造器,
用来初始化父类成员变量总结:
- 1.static final
1)static final 用来定义常量,是 Java 里定义常量的标准写法,两个修饰符作用叠加
2)static:属于类本身,不属于对象,所有对象共享这一份,不用 new 对象就能访问
3)final:不可修改,一旦赋值,值不能再改变- 代码
//抽象父类:图形 public abstract class Shape { //抽象方法:没有方法体,子类必须重写 abstract public void draw(); abstract void calcArea(); //普通成员变量 protected double area; //成员方法 public double getArea() { return area; } }// 矩形子类,继承抽象类Shape ,重写所有方法 public class Rect extends Shape{ private double length; private double width; //构造方法 public Rect(double length, double width) { this.length = length; this.width = width; } @Override public void draw() { System.out.println("矩形:长 = "+length+" 宽 = "+width); } // 重写抽象类方法 calcArea 计算面积 @Override void calcArea() { area=length*width; } }abstract public class Triangle extends Shape{ // 没全部重写父类方法的类要加abstract 关键字,变成抽象类 private double base; private double height; public Triangle(double base, double height) { this.base = base; this.height = height; } @Override public void draw() { System.out.println("三角形:底 = "+base+" 高 = "+height); } // @Override // void calcArea() { // area=(base*height)/2.0; // //// } }public class Triangle extends Shape{ //重写了父类中的全部方法,不需要变成抽象类 private double base; private double height; public Triangle(double base, double height) { this.base = base; this.height = height; } @Override public void draw() { System.out.println("三角形:底 = "+base+" 高 = "+height); } @Override void calcArea() { area=(base*height)/2.0; } }public static void main(String[] args) { // Shape shape=new Shape(); //编译报错,抽象类不能new实例 //多态写法:父类引用指向子类对象 Shape triangle=new Triangle(10.6,8.8); triangle.draw(); triangle.calcArea(); System.out.println("三角形的面积:"+triangle.getArea()); }抽象类特点
抽象类特点
1)抽象类不能直接 new 实例化,只能写子类继承它
2)子类必须重写里面的抽象方法为什么不直接用普通父类,要用抽象类?
普通类也能继承、普通方法也能重写,但没有编译期检查:
1)如果父类是普通类:你不小心写代码new 父类(),编译器不会报错,
运行时才发现逻辑错误(本应该用子类干活,结果创建了父类对象)
2)如果父类是抽象类:一旦尝试new 抽象类(),编译阶段直接报错,提前发现 bug
3)本质:抽象类给代码增加编译器校验,
强制约束:这个类只是模板,不允许创建对象,实际业务逻辑交给子类实现类比 final
final也是同样思想:
1)普通变量可以随便修改
2)final修饰变量,一旦误修改,编译报错,防止意外修改总结
抽象类的作用:定义通用模板,强制不能实例化父类,由子类实现具体逻辑;
利用编译器提前校验,防止开发时错误地创建父类对象
接口
接口概念
现实例子:USB 口、电源插座。只要符合规范,不同设备都可以接入使用
- Java 中:接口是多个类的公共行为规范,属于引用数据类型
只定义标准,不关心具体实现语法规则
使用
interface关键字定义(类用class)public interface 接口名称{ // 抽象方法,默认自带 public abstract,写的时候可以省略 void method1(); }- 编码小提示:
1)接口命名习惯大写 I 开头
2)接口名字多用形容词
3)阿里规范:接口里方法、属性不要写修饰符,保持简洁- 接口使用
1)类和接口是implements(实现)关系;类和类才是extends(继承)
2)接口不能直接 new 对象,必须写实现类,重写接口全部抽象方法3)USB 案例理解:public class 类名 implements 接口名{ // 重写所有抽象方法 }
1.USB 接口定义openDevice()、closeDevice()两个规范
2. Mouse 鼠标类、Keyboard 键盘类实现 USB 接口,各自实现打开关闭
3. 电脑 Computer 的useDevice(USB usb),只要是实现 USB 接口的设备都可以传入,
这就是面向接口编程- 接口核心特性
1)不能直接 new 接口对象,编译报错
2)接口内抽象方法默认:public abstract,只能是 public,private/protected 都不行
3)接口里抽象方法不能写方法体,实现逻辑交给实现类
4)实现类重写接口方法,访问权限必须是public,不能缩小权限
5)接口里写的变量,默认是public static final(常量),必须初始化,不能修改
6)接口没有构造方法、不能有静态代码块
7)接口编译之后,文件后缀同样是.class
8)如果实现类没有重写完接口所有抽象方法,这个类必须定义成abstract抽象类
9)JDK8 新特性:接口中可以写default默认方法(带方法体)