异常
程序运行过程中发生的错误,会中断并终止程序;
异常处理
一种机制,能让程序在异常发生时,按照预先设定异常处理预案,针对性的进行处理让程序最终恢复正常并继续运行。
try
try:包裹可能会出现异常的代码,一旦有异常立刻退出try块。
catch
catch:包含异常类型和处理代码,一旦有异常依此遍历每一个catch块,有匹配时执行该catch块中的处理代码,执行完退出整个catch块
catch:应该由小向大捕捉异常;
import java.util.*;
class CTest{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
System.out.println("start---------------------------");
try{
System.out.println("输入第一个数");
int a = sc.nextInt();
System.out.println("输入第二个数");
int b = sc.nextInt();
System.out.println("两个数字的和 "+ (a+b));
System.out.println("两个数字的商 "+ (a/b));
}catch( ArithmeticException e){
//处理
System.out.println("除数不能为0,无法计算");
e.printStackTrace(); //什么类型的异常,第几行出错
}catch( InputMismatchException e){
//处理
System.out.println("输入了不合法的数字");
e.printStackTrace();
}catch( RuntimeException e){
//处理
System.out.println("未知异常01,无法计算");
e.printStackTrace(); //什么类型的异常,第几行出错
}catch( Exception e){
//处理
System.out.println("未知异常02,无法计算");
e.printStackTrace(); //什么类型的异常,第几行出错
}
System.out.println("end---------------------------");
}//main()
}
finally
finally:有无异常总会执行代码块;解决如关闭资源前程序就触发了异常,造成某些资源无法关闭,从而引发其他程序不能正常使用这些资源;
import java.util.*;
class DTest{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
System.out.println("start---------------------------");
try{
System.out.println("输入第一个数");
int a = sc.nextInt();//出
System.out.println("输入第二个数");
int b = sc.nextInt();
System.out.println("两个数字的和 "+ (a+b));
System.out.println("两个数字的商 "+ (a/b));
//关闭资源;
/*}catch( Exception e){
//处理
System.out.println("未知异常02,无法计算");
e.printStackTrace(); //什么类型的异常,第几行出错*/
}finally{
System.out.println("看见此处代表程序已经执行了");
}
System.out.println("end---------------------------");
}//main()
}
try,catch,finally 组合
try...catch...finally try...catch try...finally
try,catch.finally 中都可以嵌套 try,catch,finally
import java.util.*;
class TryDemo01{
public static int test(int a,int b){
try{
System.out.println("haha");
return a/b; //返回值应该是2
}catch(Exception e){
return -1; //b为0时返回值应该是-1
}finally{
return -2; //离开方法前总会覆盖原返回值
}
}
public static void main(String[] args){
System.out.println( test(10,5)); // 结果都是-2
System.out.println( test(10,0)); // 结果都是-2
}//main()
}
throw
throw:手动抛出异常可以设置异常信息或抛出自定义异常
import java.util.*;
class Hours{
int age;
public void setAge(int a){
if( a<1 || a>50){
throw new ArithmeticException("哈哈!!马的年龄应在1~50之间"); //
}else{
this.age = a;
}
}
}//goat()
class HTest{
public static void main(String[] arg){
Hours h = new Hours();
try{
h.setAge(365);
}catch(ArithmeticException e){
e.printStackTrace();
}
System.out.println("1..." + h.age);
h.setAge(6);
System.out.println("2..." + h.age);
}
//运行结果
/**java.lang.ArithmeticException: 哈哈!年龄不符合
1....:0
2......:6
**/
}
throws
throws:声明方法会抛出的异常类型有时在使用方法时,并不知道需要捕捉什么类型的异常,当然可以使用Exception来捕捉将异常直接声明出来就可以避免这种状况
import java.util.*;
class Fish{
public void eat()throws NullPointerException{}
public void fly()throws ArithmeticException,InputMismatchException{}
}
class FTest{
public static void main(String[] arg){
try { //工具IDEA快捷键选中代码后 ctrl+alt+t 选6~8
Fish f1 = new Fish();
f1.eat();
f1.fly();
} catch (InputMismatchException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NullPointerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ArithmeticException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
throws:有检查异常时需要强制处理,如果不想处理检查异常可以使用throws声明该异常,其他方法调用可以处理可以继续throws异常但最后调用的方法必须处理;
import java.util.*;
class Goat{
public void eat(){
try{
Object o = Class.forName("java.util.Scanner"); //手动加载类型,以后反射技术
System.out.println( o );
}catch(Exception e){
e.printStackTrace();
}
}
public void fly()throws ClassNotFoundException{
Object o = Class.forName("java.util.scanner"); //手动加载类型,以后反射技术
System.out.println( o );
}
}//goat()
class GTest{
public static void main(String[] arg) throws ClassNotFoundException{ //抛给了JVM,但JVM不会处理该异常,
Goat g1 = new Goat(); //该程序有中断风险.
System.out.println( "start......" );
g1.eat();
g1.fly();
System.out.println( "end......" );
}
}
异常的体系
Throwable
Error(错误) Exception(异常)
RuntimeException(运行时异常)
Error:Error及子类代表JVM本身的错误,不能被程序员通过代码进行处理。
Exception:Error及子类代表运行时异常,可以被程序员通过代码进行处理。
检查异常/非检查异常
非检查异常:RuntimeException及子类,在javac编译时,不会提示和发现这种异常,不要求处理。
检查异常:Exception及子类,在javac编译时,会提示和发现这种异常,强制要求立刻做出处理,除非使用throws抛出。
/*
检查异常: 必须捕获[或方法声明]
如: Exception, IOException
public static Class<?> forName(String className)throws ClassNotFoundException
非检查异常/运行时异常: 不提示捕获
如: RuntimeException,ArithmeticException
*/
import java.util.*;
class Iphone{
public void run()throws ArithmeticException{
System.out.println( "调用了 run ...." );
}
public void eat(){
try{
Object o = Class.forName("java.util.Scanner"); //手动加载类型,以后反射技术
System.out.println( o );
}catch(ClassNotFoundException e){
e.printStackTrace();
}
}//
public void fly(){
this.run(); //不强制捕获
}
}//goat()
自定义异常
自定义异常:检查异常继承Exception
非检查异常继承RuntimeException
都需要定义四个构造器,每个构造需要调用父类对应类型的构造
import java.util.*;
class JMySuperException extends Exception{
public JMySuperException() {}
public JMySuperException(String s) {super(s);}
public JMySuperException(String s,Throwable t) {super(s,t);}
public JMySuperException(Throwable t) {super(t);}
}//
class JMyNomalException extends RuntimeException{
public JMyNomalException() {}
public JMyNomalException(String s) {super(s);}
public JMyNomalException(String s,Throwable t) {super(s,t);}
public JMyNomalException(Throwable t) {super(t);}
}//
class Jump{
//正常使用
public void eat()throws JMyNomalException{
System.out.println("aabbbcc");
}//
//正常使用
public void run(int a, int b){
try{
System.out.println( a/b ); //
}catch( JMyNomalException e ){
//}catch( JMySuperException e ){ // 应在 try 语句中抛出异常错误 JMySuperException 去掉注释会报错
e.printStackTrace(); // 如果try语句没有异常 JMySuperException 会报错
}
}//
//可以将java运行时引发的异常转换为自己的异常
public void fly(int a, int b){
try{
System.out.println( a/b );
}catch( Exception e ){ //运行时会引发ArithmeticException,会被这里抓住
throw new JMyNomalException("除数不能为0!",e.getCause()); //但我的处理是手动抛出自定义的异常(带上友好的信息)
}
}//
//可以将java运行时引发的多个异常转换为自己的异常
public void jump(int a, int b){
try{
b= b+200;
System.out.println( b );
System.out.println( a/b );
}catch(ArithmeticException|InputMismatchException|NullPointerException e ){
throw new JMyNomalException("除数不能为0!",e.getCause());
}
}//
}
class JTest{
public static void main(String[] arg){
Jump j = new Jump();
try {
j.eat();
} catch (JMyNomalException e) {
// TODO -generated catch block
e.printStackTrace();
}
try{
j.fly(10,0);
}catch( Exception e){ //此时抓住的不是 ArithmeticException也不是Exception
e.printStackTrace();//而是 JMyNomalException
}
System.out.println( "-----" );
try{
j.jump(10,2147483647);
}catch( Exception e){ //此时抓住的不是 ArithmeticException也不是Exception
e.printStackTrace();//而是 JMyNomalException
}
}
}
异常的产生
由java运行时引发,引发的异常会根据当前环境创建出一个对应的异常类型,该类型方便程序员捕获时进行处理;
由程序员手动抛出,程序员自己创建(new)一个异常类型,该类型方便程序员捕获时进行处理;