目录
友情提醒
背面试题很枯燥,加入一些戏剧场景故事人物来加深记忆。PS:点击文章目录可直接跳转到文章指定位置。 |
第三幕、
第一场)异常机制面试题
【面试官老吉,面试官潘安,面试者老王】
老吉:今天有60场面试,从早上九点,到晚上六点。我们快点开始吧。1.Error、Exception区别
老王:你姓王吗?
①Error类和Exception类的父类都是throwable类
②Error类一般是指与虚拟机相关的问题,如系统崩溃,虚拟机错误,内存空间不足,方法调用栈溢等。仅靠程序本身无法恢复和和预防,建议让程序终止。
③Exception类表示程序可以处理的异常,可以捕获且可能恢复。应该尽可能处理,而不应该随意终止异常。
王老吉:反正我不姓加。下一个问题你问吧,潘安。
潘安:程序出了问题还可以抛出异常,国家出了问题又能怎么办呢。西晋惠帝时期的八王之乱导致了五胡乱华,而我也在八王之乱中被杀了。所以:2.说一下Java中的异常处理机制的简单原理和应用。
老王:才三十二岁,你就有白头发了,Java程序员这一行不好干啊。
①异常是指java程序运行时(非编译)所发生的非正常情况或错误。异常处理机制是识别及响应错误的机制。
②Java使用面向对象的方式来处理异常,它把程序中发生的每个异常也都分别封装到一个对象中,该对象中包含有异常的信息,我们也可以自定义异常类(继承Exception或RuntimeException)。所有异常的根类为java.lang.Throwable,Throwable下面又派生了两个子类:Error(一般不关注)和Exception(合理的应该处理的异常)。
③异常分为运行时异常和编译期异常
编译器强制编译期异常必须try…catch处理或用throws声明继续抛给上层调用方法处理,所以编译期异常也称为checked异常。
④而运行异常可以用try catch抓取也可以不处理,所以编译器不强制用try…catch处理或用throws声明。
潘安:3.常见的异常
老王:ArithmeticException(算术异常)
ClassCastException (类转换异常)
IllegalArgumentException (非法参数异常)
IndexOutOfBoundsException (下标越界异常)
NullPointerException (空指针异常)
老吉:4.说一下异常处理:throw,throws和try…catch…finally
老王:如果异常一直用throw抛出总不是个事情,异常总得有处理的时候这时候需要用到throws和try…catch…finally
/*格式: try{
//可能出现异常的代码
}catch(异常类型1 对象名){
//逻辑代码
}catch(异常类型2 对象名){
//逻辑代码
}
*/
public class TestException_3 {
public static void main(String[] args) {
test2();
}
public static void test2() {
/*
运行时异常:数组下标越界异常
java.lang.ArrayIndexOutOfBoundsException: Index 10 out of bounds for length 10
*/
try {
int[] arr = new int[10];
System.out.println(arr[10]);
} catch (Exception e) {
//参数位置可能发生多态 万能捕获器 表现:Exception e = new ArrayIndexOutOfBoundsException();
e.printStackTrace(); //打印堆栈信息 ==> 将异常对象所属的类型、原因、涉及的行数打印展示在控制台
// System.out.println(e.getMessage()); //得到异常出现的原因
}
System.out.println("执行了");
}
}
try…catch…finally结构中,finlly被定义在最后位置,将一定需要被执行的代码定义在finally的内部,finally中的代码一定会被执行。
/*格式: try{
//可能出现异常的代码
}catch(异常类型1 对象名){
//逻辑代码
}catch(异常类型2 对象名){
//逻辑代码
}finally{
//定义一定需要被执行的代码
}
*/
public class TestException_3 {
public static void main(String[] args) {
test4();
}
public static void test4() {
FileInputStream fis = null;
try {
fis = new FileInputStream("hello2.txt");
int len;
while ((len = fis.read()) != -1) {
System.out.println((char) len);
}
int num = 10 / 0;
} catch (Exception e) {
e.printStackTrace();
}finally {
//这里面的代码一定会执行
try {
if (fis != null) {
fis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
System.out.println("执行了");
}
}
异常声明处理:throws(延后处理):一个方法产生了一个它不想立即处理的异常时,那么就需要在该方法的头部使用throws主动声明这个异常,告诉调用者可能出现问题,后面交给外部进行处理,以达到延后处理的目的。如下:m1方法中的异常最终交给了m3方法解决。
/* 关键字:throws 格式:
public ... 返回值类型 方法名(形参列表) throws 异常类型1,异常类型2,...,异常类型n{
//方法体
}
*/
public class TestException_4 {
public static void main(String[] args) {
m3();
}
public static void m3(){
try {
m2();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void m2() throws IOException {
m1();
}
public static void m1() throws IOException {
FileInputStream fis = new FileInputStream("hello.txt");
int len;
while ((len = fis.read()) != -1) {
System.out.println((char) len);
}
fis.close();
}
}
throw 关键字用来在程序中明确的抛出异常,什么是抛出异常呢?为了明确指出此方法不捕获这类异常,并且要让调用该方法的其他方法去捕获处理该异常。我们就使用throws明确的抛出(产生)该类异常
/*
演示手动抛出异常对象=关键字:throw
*/
public class TestException_5 {
public static void main(String[] args) {
People p = new People("张三", 140);
System.out.println(p);
//...
}
}
//------------------------------分割----------------------------
class People{
private String name;
private int age;
public People() {
}
public People(String name, int age) {
this.name = name;
//数据合理性的校验
if (age <= 0 || age > 130) {
// System.out.println("年龄不合理..."); //打印信息
// throw new RuntimeException("年龄有误!"); //抛出异常,因为是运行时异常可以处理也可以不处理
// throw new Exception("年龄有误..."); //抛出异常,因为不是运行时异常所以必须处理
throw new MyException("年龄有误...");//抛出异常,因为是运行时异常的子类可以处理也可以不处理
} else {
this.age = age;
}
}
public String getName() {
return name;}
public void setName(String name) {
this.name = name;}
public int getAge() {
return age;}
public void setAge(int age) {
this.age = age;}
@Override
public String toString() {
return "People{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
潘安:5.final,finally,finalize区别
老王:
①final用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承。
②finally是异常处理语句结构的一部分,表示总是执行。
③finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的finalize方法, finalize() 方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。例如关闭文件等。JVM不保证此方法总被调用
潘安:今天就面试到这吧,你没通过。去别的公司面试吧。
老王:为什么?
潘安:我们公司以貌取人。