异常体系的介绍
我们现在学习的异常不是为了让我们的代码以后不出现异常的情况,而是当程序出现异常之后我们该怎样处理
异常体系结构
我们一般只需要管Exception就可以‘
编译时异常和运行时异常
**为社么java将异常分为编译时异常和运行时异常
在编译阶段,java不会运行代码只会检查语法并做一些优化,而运行时异常,如果运行时异常需要代码运行才会出现异常
那为什么不将异常都设计成运行时异常呢
主要为了提醒程序员检查本地信息
而运行时异常是代码出错而导致程序出现的问题
异常在代码中的2个作用
package com.an.a;
import com.ao.Deom.Student;
public class ExceptionTest {
public static void main(String[] args) {
/*
异常作用一:异常是用来查询bug的关键参考信息
异常作用二:异常可以作为方法内部的一种特殊返回值,以便通知调用者底层的执行情况
*/
//异常作用一
Student[]arr = new Student[3];
String name = arr[0].getName();
System.out.println(name);
}
}
根据异常的信息可以锁定bug出现的位置以及bug出现的原因
注意:看异常信息从下往上看
重点:异常的作用:异常作为方法内部的一种特殊的返回值以便通知调用者底层的执行情况
public void setAge(int age) {
if(age<18||age>40){
System.out.println("赋值错误");
}else {
this.age = age;
}
package com;
public class ExceptionDemo {
public static void main(String[] args) {
Student stu = new Student();
//我们限制年龄信息在18-40岁
stu.setAge(17);
}
}
//ouput:赋值错误
此时直接在控制台中打印出来,但调用处不知道是否赋值成功,而如果方法返回异常则说明没有赋值成功
并且如果方法调用处返回异常,则后面的代码则将停止执行,而如果是仅仅打印出赋值错误则后面的代码依然会执行
JVM虚拟机默认处理异常的方式
package com;
public class ExceptionDemo {
public static void main(String[] args) {
/*
默认异常的处理方式:
1.把异常的名称 异常的原因 异常出现的位置等信息输出在控制台中
2.程序停止运行 并且异常下面的代码将不会执行
*/
System.out.println("I");
System.out.println("hava");
System.out.println(9/0);
System.out.println("a");
System.out.println("dream");
}
}
try....catch捕获异常
package com;
public class ExceptionDemo {
public static void main(String[] args) {
/*
自己捕获异常:
格式:
try{
可能出现异常的代码
}catch(异常类名 变量名){
异常的处理代码
}
*/
int[] arr = {1, 2, 4, 5, 6};
try {//此处出现了异常,程序就会在这里创建一个ArrayIndexOfBoundsException的对象
//new ArrayIndexOfBoundsException()
//然后拿着这个对象和catch小括号中对比,看小括号中的变量是否可以接受这个对象
//如果能被接受,则表示该异常被捕获(抓住)执行catch里面对应的代码
//当catch里面所有的代码执行完毕,继续执行try..catch体系外的其他代码
System.out.println(arr[10]);//该段代码可能出现异常
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("索引越界了");
}
System.out.println("看看我执行了吗");
}
}
捕获异常灵魂四问
package com;
public class ExceptionDemo {
public static void main(String[] args) {
//如果try中没有遇到问题,代码怎样执行
int [] arr = {1,2,3,4,5};
try{
System.out.println(arr[0]);//将被执行
System.out.println(arr[1]);//将被执行
}catch (ArrayIndexOutOfBoundsException e ){
System.out.println("索引越界了");//不会被执行
}
System.out.println("看看我执行了吗");//将被执行
//当try中没有出现问题
//将会把try中代码全部执行完毕,不会执行catch中的代码
//注意:只有出现了异常才会执行catch中的代码
}
}
如果多个异常但只有一个捕获语句将会出现有多语句无法被捕获,以至于代码终止运行的情况
package com;
public class ExceptionDemo {
public static void main(String[] args) {
//如果try中出现了多个问题,怎样执行
try {
System.out.println(4 / 0);//算术异常
int[] arr = {1, 3, 4, 5, 8};
System.out.println(arr[10]);//数组索引越界异常
String str = null;
str.equals("abc");//空指针异常
}catch (ArrayIndexOutOfBoundsException e){
System.out.println("出现数组下标越界异常");
}
System.out.println("看看我执行了吗");
}
}
而采取多个catch语句进行处理,将可以避免这种情况的出现
package com;
public class ExceptionDemo {
public static void main(String[] args) {
//如果try中出现了多个问题,怎样执行
// 会写多个catch与之对应
//细节:如果我们要捕获多个异常并且这些异常存在父子关系,那么父类一定要写在下面
/* try {
System.out.println(4 / 0);//算术异常
int[] arr = {1, 3, 4, 5, 8};
System.out.println(arr[10]);//数组索引越界异常
String str = null;
str.equals("abc");//空指针异常
}catch (ArrayIndexOutOfBoundsException e){
System.out.println("出现数组下标越界异常");
}catch (ArithmeticException e){
System.out.println("出现了算术异常");
}catch (NullPointerException e){
System.out.println("出现了空指针异常");
}
System.out.println("看看我执行了吗");*/
try {
System.out.println(4 / 0);//算术异常
int[] arr = {1, 3, 4, 5, 8};
System.out.println(arr[10]);//数组索引越界异常
String str = null;
str.equals("abc");//空指针异常
//jdk新特性将处理方案一样的catch放在一起写
//注意:| 不能写成||
}catch (ArrayIndexOutOfBoundsException |NullPointerException |ArithmeticException e){
System.out.println("出现数组下标越界异常");
}
System.out.println("看看我执行了吗");
}
}
package com;
public class ExceptionDemo {
public static void main(String[] args) {
//如果try中遇到的问题没有被捕获,怎么执行
//相当于try..catch..的代码白写了,最终还是交给虚拟机进行处理
int[]arr = {1,2,3,4};
try{
System.out.println(arr[10]);//new ArrayIndexOfBoundException()
}catch (NullPointerException e){//无法捕获到对应的异常
System.out.println("空指针异常");
}
System.out.println("看看我执行了吗");
}
}
package com;
public class ExceptionDemo {
public static void main(String[] args) {
//如果try中遇到了问题 那么try下面的其他代码还会执行吗、
//try下面的代码就不会执行了 将会直接跳转到对应的catch中 执行catch里面的语句体
//但是如果没有对应的catch与之对应,那么将还是会交给虚拟机进行处理
int [] arr ={1,2,3,4,5};
try{
System.out.println(arr[10]);//出现ArrayIndexOutOfBoundsException并抛出异常
System.out.println("看看我执行了吗try.....");//该处将不会执行
}catch (ArrayIndexOutOfBoundsException e){//将会处理异常
System.out.println("索引越界了");
}
System.out.println("看看我执行了吗");
}
}
异常中的常见方法
idea快捷键 ctrl+alt+t用指定语句包裹指定的代码
package com;
public class ExceptionDemo {
public static void main(String[] args) {
/*
public String getMassage() 返回此异常的详细消息字符串
public String toString() 返回此可抛出的简短描述
public void printStackTrace() 把异常的错误信息输出到控制台
*/
int [] arr = {1,2,3,4,5,6};
try{
System.out.println(arr[10]);
}catch (ArrayIndexOutOfBoundsException e){
/*final String message = e.getMessage();
System.out.println(message);//10*/
// System.out.println(e.toString());//java.lang.ArrayIndexOutOfBoundsException: 10
e.printStackTrace();//java.lang.ArrayIndexOutOfBoundsException: 10
// at com.ExceptionDemo.main(ExceptionDemo.java:12)
}
System.out.println("看看我执行了吗");
}
}
可以知道printStackTrace包含了前2种输出方法的内容,这种输出方式更详细
printStackTrace方法在底层是用System.err.println()方法进行输出的,会把异常的错误信息以红色的字体输出的控制台上
抛出异常
package com;
import java.util.Arrays;
public class ExceptionDemo {
public static void main(String[] args) {
//throws :写在方法定义处,表示声明一个异常,告诉调用者,使用此方法可能会有那些异常
//throw :写在方法内,结束方法。手动抛出异常对象,交给调用者,方法中异常下面的代码将不会执行
//需求:定义一个方法求数组的最大值
int[] arr = null;
System.out.println(arr);
int max = 0;
try{
max = getMax(arr);
}catch (NullPointerException e){
System.out.println("空指针异常");
}catch (ArrayIndexOutOfBoundsException e){
System.out.println("数组下标越界异常");
}
}
public static int getMax(int arr[])/*throws NullPointerException,ArrayIndexOutOfBoundsException*/{
//下面出现的异常都是运行时异常可以省略声明
//手动创建一个异常对象,并把这个异常交给方法的调用者处理
//此时方法就会结束,下面的代码不会再执行了
if(arr==null){
throw new NullPointerException();
}
//手动创建一个异常对象,并把这个异常交给方法的调用者处理
//此时方法就会结束,下面的代码不会再执行了
if(arr.length==0){
throw new ArrayIndexOutOfBoundsException();
}
System.out.println("看看我有没有执行");
int max = arr[0];
for (int i = 0; i < arr.length; i++) {
if(arr[i]>max){
max=arr[i];
}
}
return max;
}
}
综合练习
- GirlFriend类
package com;
public class GirlFriend {
private String name;
private int age;
public GirlFriend() {
}
public GirlFriend(String name, int age) {
this.name = name;
this.age = age;
}
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
int len = name.length();
if(len<3||len>10){
throw new RuntimeException();
}
this.name = name;
}
/**
* 获取
* @return age
*/
public int getAge() {
return age;
}
/**
* 设置
* @param age
*/
public void setAge(int age) {
if(age<18||age>40){
throw new RuntimeException();
}
this.age = age;
}
public String toString() {
return "GirlFriend{name = " + name + ", age = " + age + "}";
}
}
- 测试类
package com;
import java.util.Arrays;
import java.util.Scanner;
public class ExceptionDemo {
public static void main(String[] args) {
/*
需求:
键盘录入自己心仪女朋友的姓名和年龄
姓名的长度再3-10之间
年龄的返回再18-40岁之间
如果超出了这个范围是异常数据不能赋值,需要重新录入,一直到录入正确为止
提示:
需要考虑用户键盘录入时的所有情况
比如:录入年龄时超出范围,录入年龄时录入了abc等情况
*/
Scanner sc = new Scanner(System.in);
GirlFriend gf = new GirlFriend();
while (true) {
//创建女朋友的对象
try {
System.out.println("请输入你心仪女朋友的姓名:");
String name = sc.nextLine();
gf.setName(name);
System.out.println("请输入你心仪女朋友的年龄:");
String ageStr = sc.nextLine();
int age = Integer.parseInt(ageStr);//此时如果输入的年龄不是数字将会报错
gf.setAge(age);
} catch (NumberFormatException e) {
e.printStackTrace();
continue;
}catch ( RuntimeException e){
e.printStackTrace();
System.out.println("姓名或者年龄赋值异常");
continue;
}
break;
}
//打印女朋友的信息
System.out.println(gf);
}
}
这个习题其实比较简单,但是这次结合了异常进行优化处理,可以比较清楚的知道自己是否赋值成功并且运行时的直观感受更好
自定义异常
有时候我们遇到的问题没有一个已知的异常可以完美的表示我们现在所遇到的问题,如果年龄输入有误 姓名输入有误等等,这时候就可以使用自定义异常了
idea快捷键ctrl+N搜索
从前面的异常处理我们可以看出,前面的姓名格式和年龄范围我们用RunTimeeEXception并不能简名知意的表现出我们的异常
鉴于我们的这种情况我们可以使用自定义异常来处理
- 自定义异常类一
package com;
public class NameFormatException extends RuntimeException {
//技巧:
//NameFormat:当前异常的名字,表示姓名格式化问题
//Exception表示当前的类是一个异常类
//运行时:继承自 RuntimeException
//编译时:继承自 Exception 提醒程序员检查本地信息
public NameFormatException() {
}
public NameFormatException(String message) {//有参构造用于赋值错误信息
super(message);
}
}
- 自定义异常类二
package com;
public class AgeOutOfBoundsException extends RuntimeException{
public AgeOutOfBoundsException() {
}
public AgeOutOfBoundsException(String message) {
super(message);
}
}
- GirlFriend类
package com;
public class GirlFriend {
private String name;
private int age;
public GirlFriend() {
}
public GirlFriend(String name, int age) {
this.name = name;
this.age = age;
}
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
int len = name.length();
if(len<3||len>10){
throw new NameFormatException(name+"的长度不在3-10位之间");//表示输出的异常信息
}
this.name = name;
}
/**
* 获取
* @return age
*/
public int getAge() {
return age;
}
/**
* 设置
* @param age
*/
public void setAge(int age) {
if(age<18||age>40){
throw new AgeOutOfBoundsException(age+"不在18-40岁之间");//表示输出的异常信息
}
this.age = age;
}
public String toString() {
return "GirlFriend{name = " + name + ", age = " + age + "}";
}
}
在测试类中将catch的异常类名修改成自定义类即可
标签:java,String,System,public,println,机制,异常,黑马,out From: https://www.cnblogs.com/swtaa/p/17083012.html