java异常详解

1.

java中throw和throws:throw用在方法内部实际抛出异常的时候;throws用在方法头部(参数后面,方法体前面)。

public class Test{
 public static void main(String[] args)  {
  try {
   f();
  } catch(NoSuchMethodException e) {
   System.out.println("test2");
  }
  //用try…catch捕获并处理之后,后面的语句可以正常执行
  System.out.println("test3");
 }
 static void f() throws NoSuchMethodException {
  throw new NoSuchMethodException();
  //在抛出异常之后,执行中断,代码块后面代码不再执行,代码块外面的可以执行如果后面还有代码编译期会报错,类似return
  //System.out.println("test1");
 }
}

2.

一个java文件中最多一个public类(可以没有public类),当然内部类可以有多个public类。main方法不能去掉public。


3.

java.lang.Throwable直接已知子类: Error, Exception ;Exception包含子类RuntimeException。


Error和RuntimeException,可以不用try…catch处理或声明抛出(当然捕获或者声明抛出也没问题);非RuntimeException的Exception必须在编译前用try…catch捕获处理或声明抛出,否则编译报错。


编译报错和Error是两回事。编译报错:代码语法不正确,就可能报错,处于编译期。例如少个分号,控制台“Test.java:6: 错误: 需要';'” Error:运行期出现,不捕获或者不声明抛出,编译都可以通过,但是运行的时候会报java.lang.Error类型异常。

Error用于指示合理的应用程序不应该试图捕获的严重问题。
RuntimeException——意味着程序存在bug,如数组越界,0被除,入参不满足规范.....这类异常需要更改程序来避免(当然也可以捕获处理,但是一般都是程序有问题,不应该通过捕获来“隐藏”程序bug)。

4.

Exception:表示一个由程序员导致的错误(非RuntimeException的Exception必须用捕获或抛给上级处理,RuntimeException一般都是编程有bug)。应该在应用程序级被处理。
Error:经常用来用于表示系统错误或低层资源的错误。如何可能的话,应该在系统级被捕捉。


5.

总结:非RuntimeException的Exception要捕获处理或者声明抛出被调用者处理,要么编译都通不过;RuntimeException要尽可能的避免(属于程序bug),编译的时候检查不到


6.异常的限制

class BaseballException extends Exception{}
class Foul extends BaseballException{}
class Strike extends Foul{}

abstract class Inning {
	Inning() throws BaseballException {}
	void event() throws BaseballException {
		//此代码块中不必须抛出任何异常。为什么方法声明出抛出异常,强迫用户捕获可能在子类中重写该方法时可能产生的这种异常。
	}
	abstract void atBat() throws Strike, Foul;
	void walk() {}
}

class StormException extends Exception {}
class RainedOut extends StormException {}
class PopFoul extends Foul {}

interface Storm {
	void event() throws RainedOut;
	void rainHard() throws RainedOut;
}

public class StormyInning extends Inning implements Storm {
	//构造函数必须抛出基类构造函数的异常(因为子类构造函数肯定会调用父类构造函数的),另外可以增加别的异常。
	StormyInning() throws RainedOut, BaseballException {}
	StormyInning(String s) throws Foul, BaseballException {}
	//重写父类无异常抛出非构造方法也不能增加别的异常抛出
	//! void walk() throws PopFoul {} //Complier error
	//基类和接口里面有相同的方法,重写方法的异常以基类为准(抛出异常不能比基类多)。
	//! public void event() throws RainedOut {}
	//实现接口里面的方法,并且此时基类中没有该方法时,接口方法抛出的异常可以出现在实现方法中。
	public void rainHard() throws RainedOut {}
	//重写基类或实现接口里的方法抛出的异常不能比基类或接口的异常多(不抛出异常也可以)。
	public void event() {}
	//重写的方法可以抛出“基类异常的子类异常”。
	void atBat() throws PopFoul {}
	
	public static void main(String[] args) {
		try {
			//用子类对象的引用调用方法,将只能产生父类的异常,不能产生基类抛出的异常
			StormyInning si = new StormyInning();
			si.atBat();
		} catch(PopFoul e) {
		} catch(RainedOut e) {
		} catch(BaseballException e) {
		}
		try {
			//用基类对象的应用调用方法,将只能抛出基类的异常,不能抛出子类的异常。
			Inning i = new StormyInning();
			i.atBat();
		} catch(Strike e) {
		} catch(Foul e) {
		} catch(RainedOut e) {
		} catch(BaseballException e) {
		}
	}
}

//总结:
//1.子类重写基类的方法不能产生多于基类的异常(不包括构造方法,构造方法可以多出异常来).
//2.为什么基类没有抛出异常的方法,子类重写该方法时也不能抛出异常?如果重写的方法抛出异常,而另外的重写的方法又没有抛出异常,用第一个重写的方法替换第二个重写的方法的时候就可能出现必须捕获并处理的异常,从而导致代码执行中断。
//3.为什么重写的方法可以抛出“基类方法抛出的异常的子类异常对象”?面向接口编程的时候,基类引用指向子类对象,要捕获基类方法的异常或者异常的子类。
//4.异常在类继承和方法重写的时候只能更少,范围变“窄”。类继承的时候却可以继承基类的方法和属性等,范围变“宽”。
//5.方法抛出的异常的数目以及类型的不同不能作为方法重载的条件。
//6.try{throw new XXException();} finally{throw new YYException()},在此代码段中,没有catch,此时会发生异常丢失,系统捕捉不到到第一个异常,相当于后一个异常覆盖了前一个异常。



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值