Java.多态和异常

接口

了解了Java面对对象的三大特征分别是封装、继承、多态。
关于什么是封装和继承在之前都有分享过了,只剩这个多态,多态是什么呢?
通过接口让我们好好了解什么是多态。

生活中的接口

生活中比较常见的接口:
USB接口,国标插座,Type-C , 3.5MM , ARJ45 , Lighting接口 , HDMI , VGA, SATA, M.2 , DisplayPort,雷电口, PCI-E
这些接口有什么作用?
USB接口 USB-A

  1. 鼠标连接,键盘连接,声卡连接,麦克风,摄像头,补光灯,U盘,移动硬盘
  2. 规范,规范一个接口,都是USB设备
  3. 就像通过USB接口连接的设备本身决定了,要做什么事情。鼠标、键盘、U盘

Java中接口使用

格式:

interface 接口名 {
	成员变量
	成员方法
}

类【遵从】或者说实现接口

// 	implements 
class 类名 implements 接口 {
}

接口中成员变量和成员方法缺省属性原因:
从生活角度:USB接口规定了尺寸和连接方式,但是该接口做什么内容,是由设备决定的!!!
尺寸是固定 ==> 成员变量 缺省属性是public static final
设备做什么事情,不管,但是规定连接方式 ==> 成员方法,需要设备自己完成
缺省属性 public abstract修饰

接口使用总结

  1. 成员变量缺省属性 public static final
    成员方法缺省属性 public abstract
  2. 一个非abstract类遵从interface接口,需要强制完成接口中所有缺省属性为public abstract的成员方法
  3. 接口和接口之间,允许使用extends关键字继承,并且允许一个接口,继承多个接口
    interface A extends B, C
    生活中: 协议直接的向下兼容问题
  4. 接口中可以使用default关键字修饰方法,default方法拥有方法体,可以认为是非强制实现方法,不要求遵从接口的非abstract强制实现,JDK1.8新特征

多态

接口生活化演示

从生活中映射USB接口:

interface USB

规定USB设备必须完成的方法:

void connect();

鼠标类 implements USB

鼠标是一个USB设备,必须完成connect方法

键盘类 implements USB

键盘是一个USB设备,必须完成connect方法

USB接口在电脑上,我们需要使用USB接口

/*
从生活中映射USB接口
interface USB
规定USB设备必须完成的方法
void connect();
鼠标类 implements USB
鼠标是一个USB设备,必须完成connect方法
键盘类 implements USB
键盘是一个USB设备,必须完成connect方法
*/
/**
* USB接口
* @author Anonymous
*
*/
interface USB {
/**
* 要求所有的USB设备,必须完成的方法,告知USB接口连接之后完成的
* 功能是什么
*/
	void connect();
}
/**
* 鼠标类,遵从USB接口,实现connect方法
*
* @author Anonymous
*/
class Mouse implements USB {
	@Override
	public void connect() {
		System.out.println("鼠标连接USB接口,控制光标");
	}
}
/**
* Logi类,继承Mouse鼠标类
* 1. 鼠标设备
* 2. Logi间接遵从USB接口,是一个USB设备
* @author Anonymous
*
*/
class Logi extends Mouse {
	@Override
	public void connect() {
		System.out.println("Logi Master 2S");
	}
}
/**
* 键盘类,遵从USB接口,实现connect方法
*
* @author Anonymous
*/
class Keyboard implements USB {
	@Override
	public void connect() {
		System.out.println("键盘连接USB接口,输入设备");
	}
}
/**
* IKBC继承Keyboard类
* 1. 键盘设备
* 2. 间接遵从USB接口,也是一个USB设备
* @author Anonymous
*
*/
class IKBC extends Keyboard {
	@Override
	public void connect() {
		System.out.println("IKBC C87 静音红轴");
	}
}
/**
* PC电脑类,使用USB接口,这里需要通过USB接口连
接一个USB设备
*
* @author Anonymous
*/
class PC {
/**
* 电脑类连接USB接口连接方法,这里需要的是一
个USB设备
*
* @param usb USB接口对应的设备
*/
	public void usbConnect(USB usb) {
		// usb设备执行connect方法
		usb.connect();
	}
}
public class Demo1 {
	public static void main(String[] args) {
	// 电脑中有一个方法是使用USB接口连接USB设备
		PC pc = new PC();
		// 鼠标和键盘都是USB设备
		Mouse mouse = new Mouse();
		Keyboard keyboard = new Keyboard();
		// 电脑需要通过USB接口连接USB设备,mouse鼠标就是USB设备
		pc.usbConnect(mouse);
		// keyboard键盘也是USB设备
		pc.usbConnect(keyboard);
		// 传入一个Logi类对象
		pc.usbConnect(new Logi());
		// 传入一个IKBC类对象
		pc.usbConnect(new IKBC());
	}
}

继承生活化演示

动物园: 所有的动物都可以看做是一个Animal类
狗类:Dog
熊猫类:Panda
老虎类:Tiger
方法:
喂食动物的方法
获取动物的方法

/*
动物园:
所有的动物都可以看做是一个Animal类
狗类:Dog
熊猫类:Panda
老虎类:Tiger
方法:
喂食动物的方法
获取动物的方法
*/
/**
* 动物类
* @author Anonymous
*
*/
class Animal {
}
/**
* 狗类,Animal动物的子类
* @author Anonymous
*
*/
class Dog extends Animal {
}
/**
* 熊猫类,Animal动物的子类
* @author Anonymous
*
*/
class Panda extends Animal {
}
/**
* 老虎类,Animal动物的子类
* @author Anonymous
*
*/
class Tiger extends Animal {
}
public class Demo2 {
	public static void main(String[] args) {
		Animal animal = new Animal();
		Dog dog = new Dog();
		Tiger tiger = new Tiger();
		Panda panda = new Panda();
		// 这里传入一个Animal类对象
		feed(animal);
		// 这里可以传入Dog类对象,因为Dog类对象是Animal类的子类对象
		feed(dog);
		// 这里传入的对象是Tiger类对象,Tiger类是Animal的子类
		feed(tiger);
		// 同上
		feed(panda);
		// 数据类型强转,
		Dog dog2 = (Dog) getAnimal();
		System.out.println(dog2.getClass());
	}
/**
* 该方法的是喂食【动物】的方法
*
* @param animal 需要的参数是Animal类对象
*/
	public static void feed(Animal animal) {
	// 获取当前对象的完整包名.类名
		System.out.println(animal.getClass() + "来吃饭了!!!");
	}
/**
* 返回【动物】类对象的方法
*
* @return Animal类对象
*/
	public static Animal getAnimal() {
		// return new Animal();
		return new Dog();
		// return new Tiger();
		// return new Panda();
	}
}

多态总结

多态:父类的引用指向子类的对象,或者说接口的引用指向遵从接口的类对象,这就是多态。
作用:

  1. 拓宽方法的参数范围
    例如:
    方法参数为Animal类型可以传入Animal类型本身,或者其子类对象都可以
    方法参数为USB接口类型只要是直接或者间接遵从USB接口的类对象可以作为方法的参数传入
  2. 拓宽方法的返回值范围
  3. 简化代码开发,提高开发效率,整合数据类型

异常

生活中的异常

医院看病:
医生问你: 你怎么了?
我: 我难受
医生: 你那里难受
我: 我头疼
医生: 你为什么头痛
我: 昨天晚上喝了2斤二锅头 + 10瓶福佳白 + 1箱1664
医生:…

异常或者说错误,都讲究一个前因后果!!!处理错误,讲究对症下药!!!

代码中的异常

Throwable类

Java中所以异常的超类,在Java中所有的异常,错误的基类就是Throwable类。

Throwable

Exception 异常 可以处理,代码还有拯救的可能性
Error 错误 GG思密达

Throwable常用方法:
Constructor:

Throwable(); 
Throwable构造方法,Throwable类对象中,存储的异常或者错误信息为null
Throwable(String message); 
Throwable构造方法,Throwable类对象中,存储的异常或者错误信息为message

Method:

String getMessage(); 获取Throwable对象中存储的异常或者错误信息
String toString(); 返回当前异常或者错误的简要描述
void printStackTrace(); 展示错误的前因后果,【红色字体】

Exception和Error区别

Exception 异常,可以处置
Error 错误,不可以处置,只能避免

异常处理

捕获异常

try - catch 结构
try - catch - finally 结构 后期设计到资源问题再说
格式:

try {
// 有可能出现异常代码
} catch (/* 对应处理的异常对象 */) {
// 处理方式
}

示范:

/*
* 捕获异常问题总结:
* 1. 代码中从异常发生位置开始,之后的代码都不在运行
* 2. 代码中有多个异常,可以使用多个catch块进行捕获操作,分门别类处理
* 3. 当前情况下,只能展示异常情况,后期可以讲异常情况做成log日志文件
* 4. 异常被捕获之后代码可以正常运行。
*/
public class Demo {
	public static void main(String[] args) {
		test(10, 2, null);
	}
	public static void test(int num1, int num2, int[] arr) {
		int ret = 0;
		try {
			ret = num1 / num2;
			System.out.println("测试代码");
			arr[0] = 10;
		} catch (ArithmeticException e) {
				e.printStackTrace();
		} catch (NullPointerException e) {
				e.printStackTrace();
		}
		System.out.println("ret:" + ret);
	}
}

抛出异常

throw:在方法内抛出异常
throws:在【方法声明】位置,告知调用者当前方法有哪些异常抛出
声明的异常需要生成对应的文档注释

/*
* 抛出异常总结:
* 1. 一个代码块内,有且只能抛出一个异常
* 2. 从throw位置开始,之后的代码不在运行
* 3. 代码中存在使用throw抛出异常,在方法的声明位置必须告知调用者这里有什么异常
*
*/
public class Demo2 {
// 调用带有异常抛出的方法,如果选择继续抛出需要在当前方法的声明位置
// 告知其他调用者,这里有什么异常抛出
	public static void main(String[] args) 
		throws NullPointerException,
		ArithmeticException {
		// 调用一个带有异常抛出的方法
		// 捕获处理
		try {
			test(10, 2, null);
		} catch (ArithmeticException e) {
			System.out.println(e.getMessage());
		} catch (NullPointerException e) {
			System.out.println(e.getMessage());
		}
		// 可以继续抛出异常
		test(10, 0, null);
	}
/**
* 测试方法
*
* @param num1 int类型
* @param num2 int类型
* @param arr int类型数组
* @throws ArithmeticException 除数不能为0
* @throws NullPointerException 操作数组null地址异常
*/
	public static void test(int num1, intnum2, int[] arr)
		throws ArithmeticException,
		NullPointerException {
		// 参数合法性判断
		/*if (0 == num2 || null == arr) {
			System.out.println("InputParameter is Invalid!");
			return;
		}*/
		// 抛出异常方式来处理当前的参数合法性判断
		if (0 == num2) {
			// 有可能会导致算术异常
			throw new ArithmeticException("算术异常");
		}
		if (null == arr) {
			// 存在数组操作空指针异常
			throw new NullPointerException("数组空指针异常");
		}
		System.out.println(num1 / num2);
		arr[0] = 10;
	}
}

抛出和捕获的对比

捕获之后,代码可以正常运行,要保证处理之后的异常不会在导致其他问题。
例如:

用户名密码错误,不能采用捕获异常。
用户指定路径问题,也不能采用捕获异常。

抛出的确可以解决很多问题,并且可以让代码健壮性很强。到用户层面说什么都不能抛出异常。所谓不能抛出,是指不能讲错误信息直接甩到用户脸上。

用户密码错误情况:

  1. 捕获异常
  2. 通过异常处理 catch将错误抛出
  3. 给予用户的友好提示

为什么不使用大异常和不知道为什么出错

直接抛出Exception?
不行!!!对症下药!!!
不能所有的异常都使用Exception捕获或者抛出无法得知具体的异常类型,无法做到对症下药,
不知道为什么出错,Eclipse IDEA都会有当前错误的提示。
正常情况下,只要不是带有自定义异常的方法,通常情况下需要处理的异常,代码中都有会有声明告知。如果未处理异常,代码报错。

RuntimeException

运行时异常: JVM在运行的过程中可以非检查异常
例如:

ArrayIndexOutOfBoundException    //下标越界
NullPointerException     	//空指针
StringIndexOutOfBoundException    //下标越界
ArithmeticException

这些异常在代码中如果出现,不需要代码中强制进行捕获或者抛出处理。

自定义异常

代码运行的过程中存在一定的生活化
例如:

用户名密码错误
NoGirlFriendException     //没有女朋友异常

自定义异常格式:

class 自定义异常类名 extends Exception {
// No Fields Constructor
// String Field Constructor
}

自定义异常类名:必须Exception结尾!!!

/*
* 自定义异常
*/
class NoGirlFriendException extends Exception {
/**
* 无参数构造方法
*/
	public NoGirlFriendException() {}
/**
* 带有String类型参数的构造方法
*
* @param message 描述当前的异常信息
*/
	public NoGirlFriendException(String message) {
		super(message);
	}
}
public class Demo5 {
	public static void main(String[] args)
		throws NoGirlFriendException {
		try {
			buyOneFreeOne(false);
		} catch (NoGirlFriendException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		buyOneFreeOne(false);
	}
/**
* 买一送一方法,需要判断是不是单身狗
*
* @param singleDog boolean类型数据,true 是单身,false表示有女朋友
* @throws NoGirlFriendException 没有女朋友异常
*/
public static void buyOneFreeOne(boolean singleDog)
	throws NoGirlFriendException {
		if (singleDog) {
			throw new NoGirlFriendException("两只黄鹂鸣翠柳,你还没有女朋友");
		}
		System.out.println("买蜜雪冰城甜筒一个送保时捷一辆");
	}
}
发布了9 篇原创文章 · 获赞 3 · 访问量 262

猜你喜欢

转载自blog.csdn.net/weixin_42036089/article/details/104660509
今日推荐