异常

异常

(1)、什么是异常?java提供异常处理机制有什么用?
程序执行过程中发生了不正常的情况,而这种不正常的情况叫做:异常
Java语言是很完善的语言,提供了异常的处理方式,当程序执行过程中出现了不正常的情况,Java把该异常信息打印输出到控制台(JVM打印),共程序员参考,程序员看到异常信息之后,可以对程序进行修改,让程序更加的健壮。

package javaCoreTest;

public class ExceptionTest02 {

	public static void main(String [] args) {
		/*
		 * 程序执行到此处发生了java.lang.ArithmeticException: / by zero异常
		 * 底层new出了一个ArithmeticException异常对象,然后抛出了,由于是main方法
		 * 调用了100 / 0,所以这个异常ArithmeticException抛给了main方法,main方法
		 * 没有处理,将这个异常自动抛给了JVM,JVM最终终止程序的执行。
		 */
		System.out.println(100 / 0);
		
		//这里的hello没有输出,没有执行
		System.out.println("hello");
	}
}
package javaCoreTest;

/*
 * java语言中异常是以什么形式存在的?
 * 1.异常在Java中以类的形式存在,每一个异常类都可以创建异常对象
 */
public class ExceptionTest01 {

	public static void main(String [] args) {
		
		//通过“异常类”实例化“异常对象”
		NumberFormatException nfe = new NumberFormatException("数字格式化异常");
		System.out.println(nfe);//java.lang.NumberFormatException: 数字格式化异常
		
		//通过“异常类”创建“异常对象”
		NullPointerException npe = new NullPointerException("空指针异常发生了");
		System.out.println(npe);//java.lang.NullPointerException: 空指针异常发生了
		
		int a = 10;
		int b = 0;
		//实际上JVM在执行到此处的时候,会new异常对象:new ArithmeticException("/by zero");
		int c = a / b;
		System.out.println(a + "/" + b + "=" + c);
	}
}

(2)、异常的继承结构是怎样的?
使用UML图来描述继承结构
画UML图的工具:Rational Rose(收费)、starUML等
UML是一种统一建模语言、一种图标式语言
并不是只在java中使用,只要是面向对象的编程语言,都有UML
UML图可以描述类和类之间的关系,程序执行的流程,对象的状态等

Object
Object下有Throwable(可抛出的)
Throwale下有两个分支:Error(不可处理,直接退出JVM)和Exception(可处理的)
Exception下有两个分支:
Exception的直接子类:编译时异常【受检异常,受控异常】(要求程序员在编写程序阶段必须预先对这些异常进行处理)
RuntimeException:运行时异常【未受检异常,为受控异常】(在编写程序阶段程序员可以预先处理,也可以不管)

注:编译异常和运行异常都发生在运行阶段。编译时,异常必须在编译(编写)阶段预先处理,如果不处理编译器会报错,因此得名。所有异常都是在运行阶段发生的,因为只有程序运行阶段才可以new对象,异常的发生就是new异常对象。

编译时异常和运行时异常的区别?
**编译时异常发生的概率比较高
对于一些发生概率较高的异常,需要在运行之前对其进行预处理。
**运行时异常发生的概率比较低

(3)、java语言中对异常的处理包括两种方式:

  • 第一种方式:在方法声明的位置上使用throws关键字,抛给上一级

  • 第二种方式:使用try…catch语句进行异常的捕捉

try…catch:
-catch后面的小括号中的类型可以是具体的异常类型,也可以是该异常类型的父类型。

-catch可以写多个,建议catch的时候,精确的一个一个处理,也可以是该异常类型的父类型。

-catch写多个的时候,从上到下,必须遵守从小到大。

package javaCoreTest;

public class ExceptionTest03 {

	public static void main(String [] args) {
		/*
		 * main()方法调用doSome方法,因为doSome方法声明位置上有throws ClassNotFoundException
		   *  我们在调用doSome方法时必须对这种异常进行预先的处理,如果不处理编译器就会报错 
		 */
		
		//doSome();
	}
	
	/*
	 * 以下的方法在声明的位置上使用了:throws ClassNotFoundException
	 * 这个代码表明此方法在执行过程中,有可能会出现throws ClassNotFoundException异常
	 * 叫做类没有找到异常,这个异常的直接父类是:Exception,属于编译时异常
	 */
	public static void doSome() throws ClassNotFoundException {
		System.out.println("doSome!!!");
	}
}
package javaCoreTest;

public class ExceptionTest04 {

	/*
	 * 处理异常的第一种方法:
	 * 在方法声明的位置上继续使用:throws,来完成异常的继续上抛,抛给调用者
	public static void main(String [] args) throws ClassNotFoundException{
		doSome();
	}
	*/
	
	//第二种方式:
	//try..catch进行捕捉
	public static void main(String [] args) {
		try {
			doSome();
		}catch(ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
	
	public static void doSome() throws ClassNotFoundException {
		System.out.println("doSome!!!");
	}
}
package javaCoreTest;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

/*
 * 处理异常的第一种方式:在方法声明的位置上使用throws关键字抛出,谁调用这个方法,就抛给谁,抛给调用者来处理
 */

public class ExceptionTest05 {

	//一般不建议在main方法上使用throws,因为这个异常如果真正发生了,一定会抛给JVM,JVM只有终止
	//一般main方法中的异常建议使用try..catch进行捕捉。
	public static void main(String [] args){
		System.out.println("main begin");
		
		try {
			m1();
			//若以上代码出现异常,直接进入catch语句中执行
			System.out.println("hello");
		}catch(IOException e) {
			//e引用保存的内存地址是那个new出来异常对象的内存地址
			System.out.println("文件不存在,可能路径错误");
			System.out.println(e);//java.io.FileNotFoundException: D:\Users\SKX\Downloads\周测.docx (系统找不到指定的路径。)

		}
		
		//try..catch把异常抓住之后,这里的代码会继续执行
		System.out.println("main over");
	}
	
	private static void m1() throws IOException{
		System.out.println("m1 begin");
		m2();
		System.out.println("m1 over");
	}
	
	private static void m2() throws IOException {
		System.out.println("m2 begin");
		m3();
		System.out.println("m2 over");
	}
	
	private static void m3() throws FileNotFoundException{
		/*
		 * 编译报错的原因?
		 * 第一:这里调用了一个构造方法:FileInputStream(String name)
		 * 第二:这个构造方法的声明位置上有:throws FileNotFoundException
		 * 第三:通过类的继承结构看到:FileNotFoundException父类是IOException,IOException的父类是Exception,
		 * 最终得到,FileNotFoundException是编译时异常。
		 */
		new FileInputStream("D:\\Users\\SKX\\Downloads\\周测.docx");
	}
}

(4)、异常对象有两个非常重要的方法:
-获取异常简单的描述信息:
String msg = exception.getMessage();
-打印异常追踪的堆栈信息:
exception.printStackTrace();

package javaCoreTest;

/*
 * 异常对象有两个非常重要的方法:
	-获取异常简单的描述信息:
	String msg = exception.getMessage();
	-打印异常追踪的堆栈信息:
	exception.printStackTrace();

 */

public class ExceptionTest07 {

	public static void main(String [] args) {
		//这里只是new了异常对象,但是没有将异常对象抛出,JVM会认为这是一个普通的java对象
		NullPointerException e = new NullPointerException("空指针异常");
		String msg = e.getMessage();
		System.out.println(msg);//空指针异常
		
		//打印异常堆栈信息
		//java后台打印异常堆栈追踪信息的时候,采用了异步线程的方式打印
		e.printStackTrace();
		System.out.println("hello");
	}
}

(5)、关于try…catch中的finally
-在finally子句的代码是最后执行的,并且一定会执行,即使try语句块中的代码出现了异常。

-finally子句必须和try一起出现,不能单独编写

package javaCoreTest;

//try 和 finally,没有catch可以吗?
//可以

public class ExceptionTest08 {

	public static void main(String [] args) {
		
		/*
		 * 以下代码的执行顺序:
		 * 先执行try
		 * 再执行finally
		 * 最后执行return(return语句只要执行方法必然结束)
		 */
		
		try {
			System.out.println("try...");
			return ;
		}finally {
			System.out.println("finally....");
		}
		
	}
}
package javaCoreTest;

public class ExceptionTest09 {

	public static void main(String [] args) {
		
		try {
			System.out.println("try...");
			//退出JVM
			System.exit(0);//退出JVM之后,finally中的代码就不执行了
		}finally {
			System.out.println("finally....");
		}
	}
}

(6)、finally语句通常使用在哪些情况下?
通常在finally语句块中完成资源的释放/关闭。
因为finally中的代码比较有保障。即使try语句块中的代码出现,finally中代码也会正常执行。

package javaCoreTest;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

/*
 * 关于try..catch中的finally
 */

public class ExpectionTest07 {

	public static void main(String [] args) {
		
		FileInputStream fis = null;
		
		try {
			//创建输入流对象
			fis = new FileInputStream("C:\\course\\javase");
			
			String s= null;
			//这里一定会出现空指针异常
			s.toString();
			
			//流使用完需要关闭,因为流是占用资源的
			//fis.close();//放在这里如果上面的语句出现异常,就不会执行到此处
			
		}catch(FileNotFoundException e) {
			e.printStackTrace();
		}catch(IOException e){
			e.printStackTrace();			
		}catch(NullPointerException e) {
			e.printStackTrace();
		}finally {
			if(fis != null) {
				try {
					//close()方法有异常,采用捕捉的方式
					fis.close();
				}catch(IOException e) {
					e.printStackTrace();
				}
				
			}
		}
	}
}

(7)、自定义异常类
在实际开发中,有很多业务,这些业务出现异常之后,JDK中都是没有的,程序员可以自定义异常。

自定义异常需要两步:

  • -编写一个类继承Exception或者RuntimeException
  • -提供两个构造方法,一个无参数,一个有参数
  • 例:
 package javaCoreTest;

//自定义异常

public class MyException extends Exception{//编译时异常

	public MyException() {
		
	}
	
	public MyException(String s) {
		super(s);
	}
}

/*
 * public class MyException extends RunTimeException{//运行时异常
 * 		
 * 		public MyException(){
 * 
 * 		}
 * 
 * 		public MyException(String s){
 * 			
 * 			super(s);
 * 		}
 * }
 */

(8)、重写之后的方法不能比重写之前的方法抛出更多的异常,可以更少。
例:

package javaCoreTest;

import java.io.IOException;

//重写之后的方法不能比重写之前的方法抛出更多的异常,可以更少。

public class ExceptionTest12 {

}

class Animal12{
	
	public void doSome() {
		
	}
}

class Cat12 extends Animal12{
	
	//error
	/*public void doSome throws Exception{
		
	}*/
	
	public void doSome() {
		
	}
}


class Person{
	
	public void doOther () throws Exception{
		
	}
}

class Chinese extends Person{
	
	//编译通过
	/*public void doOther() {
		
	}*/
	
	//编译通过
	/*public void doOther () throws IOException{
		
	}*/
	
	//编译通过
	public void doOther() throws NullPointerException{
		
	}
}
package javaCoreTest;

/*
 * final finally finalize有什么区别?
 */

public class ExceptionTest11 {

	public static void main(String [] args) {
		
		//final是一个关键字,表示最终的,不变的。
		final int i = 100;
		
		//finally也是关键字,和try联合使用,使用在异常处理机制中
		try {
			
		}finally {
			System.out.println("finally...");
		}
		
		//finalize()是Object类中的一个方法,作为方法名出现
		//finalize是标识符
		
	}
}
package javaCoreTest;

import java.io.FileInputStream;
import java.io.FileNotFoundException;

//JDK8.0的新特性

public class ExceptionTest06 {

	public static void main(String [] args) {
		
		try {
			//创建输入流
			FileInputStream fis = new FileInputStream("C:\\curse\\02-javaSE");
			
			//进行数学运算
			System.out.println(100 / 0);
		}catch(FileNotFoundException | ArithmeticException | NullPointerException e) {
			System.out.println("文件不存在?数学异常?空指针异常?都有可能");//JDK8.0之后允许出现上面的写法
		}
	}
}
package javaCoreTest;

//java 面试题

public class ExceptionTest10 {

	public static void main(String [] args) {
		int result = m();
		System.out.println(result);//100
	}
	
	/*
	 * java语法规则(有一些规则是不可能破坏的):
	 * -方法体中的代码必须遵循自上而下顺序依次执行(亘古不变)
	 * -return语句一旦执行,整个方法必须结束
	 */
	
	public static int m() {
		int i = 100;
		
		try {
			return i;
		}finally {
			i++;
		}
	}
}
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值