JAVA重写异常不抛出类路径,Java基础之异常

异常

编译时检测:Exception和其子类(除了RuntimeExpection)

运行时检测:RuntimeException

编译时异常

继承自Exception的,编译时就检查,一般来自外界因素,或者语法错误,比如有时候读文件,当路径错误或者文件名打错了,就会抛出。这种类型的异常抛出后必须处理,比如在某个方法内可能出现该类型的异常,要么在方法头加上throws继续往上抛,直到某一级catch到为止。要么在方法体里try catch,这里处理过了调用时就不用再处理了。当调用该方法时,也可以用throws或者用try catch。

public class Test {

// 方法体内try-catch

public void run1() {

try {

throw new Exception();

} catch (Exception e) {

e.printStackTrace();

}

}

// 方法头throws给上级调用者

public void run2() throws Exception {

throw new Exception();

}

public static void main(String args[]) /*run2()或者在这里throws*/{

Test t = new Test();

t.run1(); // run1()方法体内已经处理,这里不用catch,也不用在main上throws

// run2()只是throws,仅提示这里可能会抛出,并没有处理,所以这里必须处理,要么继续抛(main函数上throws,要么catch)

try {

t.run2();

} catch (Exception e) {

// 实际开发肯定不能这样,必须进行相应处理

// handle code

e.printStackTrace();

}

}

}

运行时异常

继承自RuntimeException,编译时不会抛出,直到运行到那行代码才抛出,此时问题发生无法让功能正常进行,如数组下边越界,更多是由于调用者的原因(代码写得有问题,比如本应该是arr[i]写成了arr[i+1])或者引发了内部状态改变导致,异常抛出后可处理可不处理,编译让其通过,运行时强制停止,让调用者去处理。即方法头不用加throws,方法体内也不用catch。

public class Test {

// 不用处理

public void run1() {

throws new RuntimeException();

}

public static void main(String args[]) {

Test t = new Test();

t.run1(); // 调用也不处理,程序终止

// 调用时正确处理,程序继续

try {

t.run1();

} catch (Exceptipon e) {

// 实际开发肯定不能这样,必须进行相应处理

// handle code

e.printtStackTrace();

}

}

}

自定义异常类

public class MyException extends RuntimeException {

// 构造函数一般用父类的

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

}

// another file

public class Test {

public void run() {

if (/*expression*/) {

throws new MyException("自定义异常") // 传入实参给了super(s)

}

else {

// code...

}

}

public static void main(String args[]) {

Test t = new Test();

try {

t.run();

} catch (RuntimeException e) {

// handle code

e.printStackTrace();

}

}

}

什么时候用try,什么时候用throws

能自己解决的用try,比如数组下标越界,调用者可以事先作判断下标的范围,防止该异常发生。即使造成异常,程序终止,也可以通过修改代码解决。

不能自己解决的,比如IO异常,文件没有被关闭,数据库连接异常,访问不存在的路径等,我们没有办法自己搞定,只能上报上级(throws),试想如果路径出错了,根本就没有这个文件。而又try-catch,捕获后程序正常运行,并没有把路径错误给暴露出去。(路径都错了后面的程序能正常运行吗?)这就叫“把异常给吃(隐藏)了”。相反,如果继续抛出,一直到程序终止,用户看到异常信息就知道是路径错了,需要改路径。这样的异常写代码的人根本无法处理,不是改代码就可以的,毕竟程序猿怎么改也可能有人把路径写错:)

异常的其他注意事项

try -catch还可搭配finally使用,无论捕获异常否,finally里面的内容必然或执行,一般用于关闭文件、关闭连接、释放资源等。

也可以不catch,只try-finally。比如某个函数可能抛出异常,我不想处理,但是又必须要把某件事给做了,这是就可以用这种结构。

throw了多少(n)个异常,就要catch多少(n)个异常。

父类方法头若没有throws异常,子类方法覆盖父类时候,子类的方法头不能throw异常。

throw是确确实实抛出了一个异常,而throws是提醒、标注这儿可能出现异常,并没有实际抛出。

异常的一个形象的例子

上面说的什么时候用try,什么时候用throws还是很抽象的,我也不知带自己在说什么。和实际生活结合起来,看下面这个例子就豁然开朗了,为了直观,部分代码采用中文,注意这很不规范,仅为了便于理解异常。

// 老师用电脑上课

class 电脑蓝屏异常 extends RuntimeException {

电脑蓝屏异常(String s) { super(s); }

}

class 电脑烧坏异常 extends RuntimeException {

电脑烧坏异常(String s) { super(s); }

}

// 电脑烧坏时,午饭自己解决,抛出这个异常个老板,让老板给出解决方案

class 上报老板异常 extends Exception {

上报老板异常(String s) { super(s); }

}

class Computer {

// 电脑运行状态标志位,0位正常运行

private int flag = 1;

public void run() {

if (flag == 1) {

throw new 电脑蓝屏异常("你的电脑蓝屏啦!");

} else if (flag == -1) {

throw new 电脑烧坏异常("你的电脑烧坏啦!");

} else {

System.out.println("老师上课中...");

}

}

public void reset() {

// 重启后正常运行,标志位置0

flag = 0;

// 重启电脑

System.out.println("电脑重启中...");

}

}

public class Teacher {

public static void main(String args[]) throws 上报老板异常 {

Computer pc = new Computer();

try {

pc.run();

} catch(电脑蓝屏异常 e) {

System.out.println("同学们,电脑出了点小毛病,大家等几分钟就好了");

// 蓝屏了可以自己处理,重启一下电脑就行,所以

pc.reset();

pc.run();

} catch(电脑烧坏异常 e) {

System.out.println("同学们,这节课我们不能继续上课了,自习");

e.printStackTrace();

// 烧坏了,没办法自己解决,要么拿去给修电脑的,要么上报给老板买个新的

// 所以继续抛向上级

throw new 上报老板异常("老板..电脑..坏了..需要买新的");

}

}

}

flag设置为1,说明电脑蓝屏了,运行以上代码,打印如下信息,可以看到,正确处理了异常后,老师又开始上课了。

同学们,电脑出了点小毛病,大家等几分钟就好了

电脑重启中...

老师上课中...

flag设置了-1,说明电脑烧坏了,会打印以下信息。抛出异常。

同学们,这节课我们不能继续上课了,自习

Test.电脑烧坏异常: 你的电脑烧坏啦!

at Test.Computer.run(Teacher.java:21)

at Test.Teacher.main(Teacher.java:39)

Exception in thread "main" Test.上报老板异常: 老板..电脑..坏了..需要买新的

at Test.Teacher.main(Teacher.java:50)

同学们,这节课我们不能继续上课了,自习

注意:以上代码虽然很多中文,但是可以直接编译运行成功的。因为默认编码方式是UTF-8。

by @sunhaiyu

2016.12.12

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值