一、throw 和 throws 的区别?
抛出异常有三种形式,一是throw,一个throws,还有一种系统自动抛异常。下面它们之间的异同。
(1)系统自动抛异常
当程序语句出现一些逻辑错误、语义错误或类型转换错误时,系统会自动抛出异常:(举个栗子)
public static void main(String[] args) {
int a = 5, b =0;
System.out.println(a/b);
//function();
}
此时系统会抛出ArithmeticException(算术异常)。
Exception in thread "main" java.lang.ArithmeticException: / by zero
at basis.ByZero.main(ByZero.java:7)
或者:
public static void main(String[] args) {
String s = "abc";
System.out.println(Double.parseDouble(s));
//function();
}
系统会自动抛出NumberFormatException(数据格式异常)。
Exception in thread "main" java.lang.NumberFormatException: For input string: "abc"
(2)throw
throw是语句抛出一个异常,一般是在代码块的内部,当程序出现某种逻辑错误时由程序员主动抛出某种特定类型的异常。
public static void main(String[] args) {
String s = "abc";
if(s.equals("abc")) {
throw new NumberFormatException();
} else {
System.out.println(s);
}
//function();
}
运行时,系统会抛出NumberFormatException(数据格式异常):
Exception in thread "main" java.lang.NumberFormatException: For input string: "abc"
(3)throws
throws是方法可能抛出异常的声明。(用在声明方法时,表示该方法可能要抛出异常。
public void function() throws Exception{......}
public class testThrows {
public static void function() throws NumberFormatException {
String s = "abc";
System.out.println(Double.parseDouble(s));
}
public static void main(String[] args) {
try {
function();
} catch (NumberFormatException e) {
System.err.println("非数据类型不能强制类型转换。");
//e.printStackTrace();
}
}
}
运行时控制台输出:
非数据类型不能强制类型转换。
(4)throw与throws的比较
- throws出现在方法函数头;而throw出现在函数体。
- throws表示出现异常的一种可能性,并不一定会发生这些异常;throw则是抛出了异常,执行throw则一定抛出了某种异常对象。
- 两者都是消极处理异常的方式(这里的消极并不是说这种方式不好),只是抛出或者可能抛出异常,但是不会由函数去处理异常,真正的处理异常由函数的上层调用处理。
(5)编程习惯
在写程序时,对可能会出现异常的部分通常要用try{...}catch{...}去捕捉它并对它进行处理;用try{...}catch{...}捕捉了异常之后一定要对在catch{...}中对其进行处理,那怕是最简单的一句输出语句,或栈输入e.printStackTrace();
如果是捕捉IO输入输出流中的异常,一定要在try{...}catch{...}后加finally{...}把输入输出流关闭;
如果在函数体内用throw抛出了某种异常,最好要在函数名中加throws抛异常声明,然后交给调用它的上层函数进行处理。
二、final、finally、finalize 有什么区别?
原文链接:https://www.cnblogs.com/ktao/p/8586966.html
(1)final
final是用来修饰类、方法、变量的关键字,被 final 修饰的类不能被继承,final类中的所有成员方法都会被隐式的定义为 final 方法。
final 修饰的方法不能被重写;
final 修饰的基本数据类型的变量是常量,定义时必须初始化,不能再次被赋值;final 修饰引用类型的数据(String 除外)时,其引用不可被修改,但是引用的对象中的数据可以被修改。
(2)finally
finally作为异常处理的一部分,它只能用在try/catch语句中,并且附带一个语句块,表示这段语句最终一定会被执行(不管有没有抛出异常),经常被用在需要释放资源的情况下。(×)(这句话其实存在一定的问题)。
(3)finallize
finalize()是在java.lang.Object里定义的,也就是说每一个对象都有这么个方法。这个方法在gc启动,该对象被回收的时候被调用。其实gc可以回收大部分的对象(凡是new出来的对象,gc都能搞定,一般情况下我们又不会用new以外的方式去创建对象),所以一般是不需要程序员去实现finalize的。
特殊情况下,需要程序员实现finalize,当对象被回收的时候释放一些资源,比如:一个socket链接,在对象初始化时创建,整个生命周期内有效,那么就需要实现finalize,关闭这个链接。
使用finalize还需要注意一个事,调用super.finalize();
一个对象的finalize()方法只会被调用一次,而且finalize()被调用不意味着gc会立即回收该对象,所以有可能调用finalize()后,该对象又不需要被回收了,然后到了真正要被回收的时候,因为前面调用过一次,所以不会调用finalize(),产生问题。 所以,推荐不要使用finalize()方法,它跟析构函数不一样。
3、try-catch-finally 中哪个部分可以省略?
catch 和 finally 语句块可以省略其中一个。
try-finally语句块,不能捕获异常,只能释放资源,通常用在业务分层程序中的底层模块。
4、try-catch-finally 中,如果 catch 中 return 了,finally 还会执行吗?
会。try、catch、finally里面均允许存在return语句,但是,在 finally 中不建议使用 return 语句,有可能导致程序无法正常返回。在try或 catch 中执行 return 语句不影响 finally 中语句的执行。当 try 或 catch 中的 return 语句将要返回时,程序会检测发现存在 finally 语句,此时程序会跳进 finally 语句块中执行,执行完 finally 中的语句后,然后再返回到原来将要执行的 return 语句,方法返回,程序结束。
(1)try和catch中均有return(finally中不包含return):
package basis.exception;
public class ByZero {
public static void main(String[] args) {
System.out.println(testReturn());
}
public static String testReturn(){
try{
System.out.println(3/0);
return "try";
}catch (Exception e){
e.printStackTrace();
return "catch";
} finally {
System.out.println("资源释放。");
}
}
}
当 try 和 catch 中均包含 return 语句时(finally不包含return语句),如果 try 中代码不发生异常,此时,方法在 try 语句中的 return 返回并结束(当然,返回前会先执行完 finally 中的语句);如果 try 中的代码发生了异常,那么程序在执行完 finally 中的语句后,从 catch 语句块中的 return 语句返回并结束。
(2)try和catch、finally中均包含return:
package basis.exception;
public class ByZero {
public static void main(String[] args) {
System.out.println(testReturn());
}
public static String testReturn(){
try{
System.out.println(3/1);
return "try";
}catch (Exception e){
e.printStackTrace();
return "catch";
} finally {
System.out.println("资源释放。");
return "finally";
}
}
}
如果 try 和 catch、finally中均包含return 语句,我们依旧分情况 讨论,不发生异常时,程序执行到 try 中的 return 语句时会转去执行 finally 中的语句,并在 finally 返回并结束;发生异常时,程序执行到 catch 中的 return 语句时会转去执行 finally 中的语句,并在 finally 返回并结束。
所以,finally 中的 return 语句会屏蔽掉其他return 语句,容易导致程序不能正常放回并结束。
(3)面试题:异常返回和i++
package basis.exception;
public class ByZero {
public static void main(String[] args) {
System.out.println(testReturn());
}
public static int testReturn(){
int i = 10;
try{
return i++;
}catch (Exception e){
return i++;
} finally {
i++;
System.out.println("资源释放。i="+i);
}
}
}
先说运行结果:方法 testReturn 返回 10,finally 语句中输出 i = 12。为什么呢?
程序运行到 try 中的 return 语句时,此时(i++)的值为 10 ,程序在将要返回 10 时,发现存在 finally 语句块,于是,先把结果 10 保存在临时变量中,转而去执行 finally 语句,finally 语句执行完后输出 i 的值为 12 。待 finally 语句执行完成后,再回到 try 中,然后返回 保存在临时变量中的 10 并结束。
5、常见的异常类有哪些?
常见的异常类有哪些?
异常非常多,Throwable 是异常的根类。
Throwable 包含子类 错误-Error 和 异常-Exception 。
Exception 又分为 一般异常和运行时异常 RuntimeException。
运行时异常不需要代码显式捕获处理。
下图是常见异常类及其父子关系:
Throwable
| ├ Error
| │ ├ IOError
| │ ├ LinkageError
| │ ├ ReflectionError
| │ ├ ThreadDeath
| │ └ VirtualMachineError
| │
| ├ Exception
| │ ├ CloneNotSupportedException
| │ ├ DataFormatException
| │ ├ InterruptedException
| │ ├ IOException
| │ ├ ReflectiveOperationException
| │ ├ RuntimeException
| │ ├ ArithmeticException
| │ ├ ClassCastException
| │ ├ ConcurrentModificationException
| │ ├ IllegalArgumentException
| │ ├ IndexOutOfBoundsException
| │ ├ NoSuchElementException
| │ ├ NullPointerException
| │ └ SecurityException
| │ └ SQLException