java基础---异常处理

=====什么是Throwable?Exception?error?Exception有哪两种?什么是检查型异常和非检查型异常呢?常见的非检查型异常有什么呢?他们之间有什么区别?

Throwable是所有异常和错误的超类父类,包括了它的子类Error和Exception.
Exception是异常,包括两种异常checkedException和UnCheckedException,区别在于他们的处理方式。检查型异常需要使用try, catch和finally关键字在编译期进行处理,否则会出现编译器会报错。对于非检查型异常则不需要这样做。
 
Java中所有继承自java.lang.Exception类的异常都是检查型异常。
 
所有继承自RuntimeException的异常都被称为非检查型异常。包括IllegalArgumentException、IllegalStateException、NullPointerException、IndexOutOfBoundsException。非检查型异常都是程序运行时候出现的异常,不需要进行捕获,因为虚拟机默认会printStackTrace()打印错误的堆栈信息。
 
Error是错误,一般包括编译型错误或者系统的错误,如java.lang.StackOverFlowError 或者 Java.lang.OutOfMemoryError 之类的。
 
 
===常见的OOM内存溢出和常见stackOverFlow异常?
 
 
 
 
===常见的runtimeException非法输入,数组越界,空指针异常
illegalArgument,illegalStateException
nullPointerException,indexOutofbounds
 
 
===?为什么RuntimeException使用try catch是没有用的?
因为往往代码运行初期没问题,但是运行到一定程度了就会出问题,而这种问题是代码本身没写好,你try...catch了,bug依然是存在的。
 
 
===如何处理空指针nullpointerexception异常问题,有什么最佳实践方式?
数据库查询,远程调用和集合元素返回时要判断是否为空。
 
 
 
===?区分编译时异常和运行时异常?
indexOutOf异常是runtimeException
编译时异常:语法不对
运行时异常:代码逻辑有错
编译时异常一般指的是编译器对于语法规范的一些检查,如果不同过的话,现在的大部分编译器就会及时提示。不改正时无法进行编译的。而运行时异常(runtime exception),则不会影响程序的编译,而是在运行过程中调用某部分方法时,抛出异常。如下题,很多人会抓住刚学的知识点,忽略其他部分,正确答案应该是A。语句的书写时没有错误的,而在运行时会发生下标越界的错误。
 
 
 
 
 
===================================================================
补充部分
 
 
 
===try--catch---finally的处理执行顺序
1、不管有木有出现异常,finally块中代码都会执行;
2、当try和catch中有return时,finally仍然会执行;
3、finally是在return后面的表达式运算后执行的(此时并没有返回运算后的值,而是先把要返回的值保存起来,管finally中的代码怎么样,返回的值都不会改变,任然是之前保存的值),所以函数返回值是在finally执行前确定的;
4、finally中最好不要包含return,否则程序会提前退出,返回值不是try或catch中保存的返回值。
总结:finally一定会执行,try.catch中的return参数一定会先保存起来,等finally执行完之后再返回,如果finally直接返回return,那么就会丢失掉try.catch里面的参数。
 
 
===java异常的最佳实践
1.像空指针,数组越界等等runtimeException尽量预先检查代码排除掉。空指针的可能出现位置:数据库查询,集合数据处理都要进行空判断。
2.不能将大面积的代码直接包在try...catch里面,必须区分稳定代码和不稳定的代码。
3.事务回滚在catch块中必须手动回滚
4.finally块必须对资源对象,流对象进行关闭,也必须try-catch
 
 
=====如何自定义异常,并且如何手动抛出异常?
异常是一个类并实例化成对象,所以必须要用类去继承Exception创建自定义的异常类。
public class MyException extends Exception{
     private int id;
     public MyException(String message,int id){
         super(message);//定义构造方法,继承父类
         this.id = id;
     }
     public int getId(){
         return id; 
     }
}
//创建测试类
public class TestException{
     public void regist(int num) throws MyException{
         if( num < 0 ){//手动抛出异常
          throw new MyException(“人数为负值”,1);
          } 
     }
     public void manage(){
         try{
          regist(-100);//抛出的异常在调用它的方法中进行处理
     }catch(MyException e ){
          System.out.println(“人数不能够为负数");
           e.printStackTrace();   
     } 
     }
}
 
 
 
===?为什么在catch块里面能够再抛出一个RuntimeException并且不需要catch处理,但是不能够抛出一个Exception呢?为什么在catch块里面抛出了一个RuntimeException之后就能够中断线程的执行呢?是不是只能够通过抛RuntimeException来中断线程呢?
1.因为RuntimeException是不需要被catch的,而Exception包括RuntimeException和checkedException检查型异常,检查型异常是需要catch处理的。
2.抛出RuntimeException的时候程序就会中断了!!并且如果你不去catch这个RuntimeException的时候程序就会中断,否则你catch了就会继续执行。
3.不只能通过抛RuntimeException来中断进程,因为其他的异常必须try catch处理掉。也可以抛其他异常,然后break;来中断进程。
 
 
 
 
 
===?如何在遍历一个集合的时候删除掉某个元素或者添加元素?为什么要用迭代器来进行删除,而不用集合自带的add或者delete方法呢? 比如说add,remove之类的操作, 搞不好就会抛ConcurrentModificationException,为什么会抛出这个异常呢?
因为有个参数modCount记录了集合被修改的次数,用集合自带的方法进行修改的时候,这个modCount直接就改变了。
用迭代器进行迭代的时候,想删除某个元素,就会比较这个参数和另一个期望参数的值,如果相同就会删掉这个元素,否则就会抛出异常。因为使用迭代器进行迭代的时候是能够一直保证mo
 
Iterator iterator = list.iterator();
while(iterator.hasNext()){
     Object obj = iterator.next();
     iterator.delete();//必须使用这种删除方式否则报错
     //list.remove(..)这种方式删除必定报错,抛出ConcurrentModificaionException异常
}
 
 
===?为什么会报出ConcurrentModificationException的异常?
final void checkForComodification() {
        if (modCount != expectedModCount)
        throw new ConcurrentModificationException();
    }
抛出异常的判断是以上这句,迭代过程中会判断这两个参数
源码是这么描述的:ArrayList 继承了 AbstractList, 其中AbstractList 中有个modCount 代表了集合修改的次数。在ArrayList的iterator方法中会判断 expectedModCount与 modCount是否相等,如果相等继续执行,不相等报错,只有iterator的remove方法会在调用自身的remove之后让 expectedModCount与modCount再相等,所以是安全的。
【错误原因】 对于remove操作,list.remove(o)的时候,只将modCount++,而expectedModCount值未变,那么迭代器在取下一个元素的时候,发现该二值不等,则抛ConcurrentModificationException异常。 
【解决办法】 
  • remove:用iterator提供的原生态remove() 
  • add:同remove就错了,iterator没有提供原生的add()方法。要用新的容器暂存,然后再遍历结束后,全部添加到原容器当中。 
  • set/list:这两类常用容器,就用上面说的方法remove(), add()就好了。 
  • map:直接使用ConcurrentHashMap就ok。为什么别的容器,不也实现个concurrent版本直接用。。?库里不搞,自己搞。 
posted @ 2018-07-31 16:51  buptyuhanwen  阅读(132)  评论(0编辑  收藏  举报