在编程语言和类型论中,多态(英语:polymorphism)指为不同数据类型的实体提供统一的接口。 多态类型(英语:polymorphic type)可以将自身所支持的操作套用到其它类型的值上。
多态是面向对象程序设计(OOP)的一个重要特征,指同一个实体同时具有多种形式,即同一个对象,在不同时刻,代表的对象不一样,指的是对象的多种形态。
可以把不同的子类对象都当作父类来看,进而屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,统一调用标准。
- 多态的前提1:是继承
- 多态的前提2:要有方法的重写
- 父类引用指向子类对象,如:Animal a = new Cat();
- 多态中,编译看左边,运行看右边
public class TestDemo {
public static void main(String[] args) {
Animal a = new Animal();
Cat c = new Cat();
Dog d = new Dog();
a.eat();
c.eat();
d.eat();
//a.play();
c.play();
d.play();
Animal a2 = new Cat();
Animal a3 = new Dog();
a2.eat();
//a2.play();// 多态对象把自己看做父类类型,不能使用子类的特有方法
}
}
class Animal {
public void eat() {
System.out.println("小动物Animal吃啥都行~");
}
}
class Cat extends Animal {
@Override
public void eat() {
System.out.println("小猫爱吃小鱼干~");
}
public void play() {
System.out.println("小猫Cat跳得老高啦~");
}
}
class Dog extends Animal {
@Override
public void eat() {
System.out.println("小狗爱吃肉骨头~");
}
public void play() {
System.out.println("小狗Dog跑得老快啦~");
}
}
1.3 多态的好处
- 多态可以让我们不用关心某个对象到底具体是什么类型,就可以使用该对象的某些方法
- 提高了程序的可扩展性和可维护性
前提:多态对象把自己看做是父类类型
- 成员变量: 使用的是父类的
- 成员方法: 由于存在重写现象,所以使用的是子类的
- 静态成员: 随着类的加载而加载,谁调用就返回谁的
public class TestDemo2 {
public static void main(String[] args) {
Animal2 a = new Animal2();
Dog2 d = new Dog2();
Animal2 a2 = new Dog2();
d.eat();
d.play();
System.out.println(a2.sum);
a2.eat();
a2.play();
}
}
class Animal2 {
int sum = 10;
public void eat() {
System.out.println("吃啥都行");
}
public static void play() {
System.out.println("玩啥都行");
}
}
class Dog2 extends Animal2 {
int sum = 20;
@Override
public void eat() {
System.out.println("小狗爱吃肉包子!");
}
public static void play() {
System.out.println("小狗爱打滚儿~");
}
}
1.3.3 案例练习2
public class TestExec {
public static void main(String[] args) {
Car c = new Car();
System.out.println(c.getColor());
c.start();
c.stop();
BMW b = new BMW();
System.out.println(b.color);
b.start();
b.stop();
Car c2 = new BMW();
c2.start();
c2.stop();
}
}
class Car {
private String brand;
private String color;
private double price;
private double size;
public void start() {
System.out.println("启动我心爱的小车车~");
}
public void stop() {
System.out.println("赶紧刹车~");
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public double getSize() {
return size;
}
public void setSize(double size) {
this.size = size;
}
}
class BMW extends Car {
String color = "五彩斑斓的黑";
@Override
public void start() {
System.out.println("咻咻咻~发射成功");
}
}
class TSL extends Car {
String color = "黑不溜秋的白";
public void fly() {
System.out.println("哎呀!我的小车车飞起来啦了~");
}
}
2 异常
2.1 概述
Java Exception 异常处理机制其实起源很早,所以它也不是个什么新鲜的东西,如果您对Exception机制一点都不了解,没关系,只是国内通常接触新事物的时间都相对的要晚老美几年,但了解Java Exception机制对Java开发人员来说是必要的,不过Exception 异常处理机制也并没有固定,在Anders 的眼里它也是一个试验性的东西。 理论上异常处理划分为两个模型(中止模型与继续模型),但实际使用方面我们对中止模型用的比较多,这个模型比较实用,而继续模型则不是那么的应用普遍,多少是耦合的过于紧密。
异常是一些用来封装错误信息的对象
它由异常的类型、提示信息、报错的行号提示三部分组成
当程序中遇到了异常,通常有两种处理方式:捕获或者向上抛出
当一个方法抛出异常,调用位置可以不做处理继续向上抛出,也可以捕获处理异常
大家可以结合生活中的例子:如果工作中遇到了问题,我们可以选择自己处理(捕获),或者交给上级处理(抛出)
- 捕获方式
- 抛出方式
对于不想现在处理或者处理不了的异常可以选择向上抛出
方式:在方法上设置异常的抛出管道,即:
在可能会会发生异常的方法上添加代码:
throws 异常类型
public class ExceptionDemo2 {
//public static void main(String[] args) throws Exception {//因为没人解决了,不推荐
public static void main(String[] args) {
//method1();//测试暴露异常
//method2();//测试异常解决方案一
f3();//在method3()被调用之前处理它的异常
//method3();//测试异常解决方案二
}
private static void f3() {//本方法用于解决method3()抛出的异常
try{
method3();//业务是f3处理调用method3()时抛出的异常
}catch (Exception e){
System.out.println("请输入正确的数据!");
}
}
private static void method3()
throws InputMismatchException,ArithmeticException,Exception{
//1.复写刚刚的业务代码
System.out.println("请您输入要计算的第一个数:");
int a = new Scanner(System.in).nextInt();
System.out.println("请您输入要计算的第二个数:");
int b = new Scanner(System.in).nextInt();
System.out.println(a/b);
}
private static void method2() {
try{
//1.复写刚刚的业务代码
System.out.println("请您输入要计算的第一个数:");
int a = new Scanner(System.in).nextInt();
System.out.println("请您输入要计算的第二个数:");
int b = new Scanner(System.in).nextInt();
System.out.println(a/b);
}catch(InputMismatchException e){//注意导包
System.out.println("请输入正确的数据类型!");
e.printStackTrace();//打印错误信息到控制台
}catch(ArithmeticException e){
System.out.println("除数不能为0!");
}catch(Exception e){
System.out.println("输入的数据不正确!请重新输入!");
}
}
private static void method1() {
//1.提示并接收用户输入的两个整数
System.out.println("请您输入要计算的第一个数:");
int a = new Scanner(System.in).nextInt();
System.out.println("请您输入要计算的第二个数:");
int b = new Scanner(System.in).nextInt();
//2.打印接收到两个整数的除法结果
System.out.println(a/b);
//输入任意一个小数:InputMismatchException--输入不匹配异常
//除数为0:ArithmeticException--算数异常
}
}
2.4 catch 和 throws
异常处理只有两种方式: catch 和 throws,所以必须二选一
由于Java语法本身的特点,需要开发者事先考虑异常如何处理,也就是我们常说的:“未雨绸缪”
对于初级开发者来说,我们可能会捕获,但不处理异常
try {
…
} catch(Exception e) {
}
底层异常,应该向前抛到前面处理
经验少时,不知道该在什么位置捕获处理,应该选择 throws
但是大家需要注意,在异常抛出时,有些异常比如运行时异常,可能并不会强制要求抛出此异常,调用时也没有报错显示需要额外处理,这个时候就需要大家平时多积累,掌握良好的编码习惯了,手动添加代码进行预处理,增强程序的健壮性了。
程序错误分为三种:
编译错误(checked异常);
运行时错误(unchecked异常);
逻辑错误;
- 编译错误是因为程序没有遵循语法规则,编译程序能够自己发现并且提示我们错误的原因和位置,这个也是大家在刚接触编程语言最常遇到的问题。
- 运行时错误是因为程序在执行时,运行环境发现了不能执行的操作。
- 逻辑错误是因为程序没有按照预期的逻辑顺序执行。异常也就是指程序运行时发生错误,而异常处理就是对这些错误进行处理和控制。
- throws
用在方法声明处,其后跟着的是异常类的名字
表示此方法会抛出异常,需要由本方法的调用者来处理这些异常
但是注意:这只是一种可能性,异常不一定会发生 - throw
用在方法的内部,其后跟着的是异常对象的名字
表示此处抛出异常,由方法体内的语句处理
注意:执行throw一定抛出了某种异常
Java中可以定义被abstract关键字修饰的方法,这种方法只有声明,没有方法体,叫做抽象方法.
Java中可以定义被abstract关键字修饰的类,被abstract关键字修饰的类叫做抽象类
- 如果一个类含有抽象方法,那么它一定是抽象类
- 抽象类中的方法实现交给子类来完成
- abstract 可以修饰方法或者类
- 被abstarct修饰的类叫做抽象类,被abstract修饰的方法叫做抽象方法
- 抽象类中可以没有抽象方法
- 如果类中有抽象方法,那么该类必须定义为一个抽象类
- 子类继承了抽象类以后,要么还是一个抽象类,要么就把父类的所有抽象方法都重写
- 多用于多态中
- 抽象类不可以被实例化
public class AbstractDemo {
public static void main(String[] args) {
//new Phone();
Phone p = new XM();
p.call();
p.message();
p.money1();
p.money2();
}
}
abstract class Phone {
public void call() {
System.out.println("正在打电话~");
}
public void message() {
System.out.println("正在发短信~");
}
public void message2() {
System.out.println("正在发短信~");
}
abstract public void money1();
abstract public void money2();
}
class XM extends Phone {
@Override
public void money1() {
System.out.println("实现父类未实现的方法");
}
@Override
public void money2() {
System.out.println("实现父类未实现的方法2");
}
}
3.3.2 总结
abstract注意事项:
抽象方法要求子类继承后必须重写。
那么,abstract关键字不可以和哪些关键字一起使用呢?以下关键字,在抽象类中。用是可以用的,只是没有意义了。
- private:被私有化后,子类无法重写,与abstract相违背。
- static:静态优先于对象存在,存在加载顺序问题。
- final:被final修饰后,无法重写,与abstract相违背。



