黑马程序员_JAVA:异常

------- <a href="http://www.itheima.com" target="blank">android培训</a>、<a href="http://www.itheima.com" target="blank">java培训</a>、期待与您交流! ----------



异常:就是不正常。程序在运行时出现的不正常情况。其实就是程序中出现的问题。这个问题按照面向对象思想进行描述,并封装成了对象。因为问题的产生有产生的原因、有问题的名称、有问题的描述等多个属性信息存在。当出现多属性信息最方便的方式就是将这些信息进行封装。异常就是java按照面向对象的思想将问题进行对象封装。这样就方便于操作问题以及处理问题。


  出现的问题有很多种,比如角标越界,空指针等都是。就对这些问题进行分类。而且这些问题都有共性内容比如:每一个问题都有名称,同时还有问题描述的信息,问题出现的位置,所以可以不断的向上抽取。形成了异常体系。

--------java.lang.Throwable:
Throwable:可抛出的。
    |--Error:错误,一般情况下,不编写针对性的代码进行处理,通常是jvm发生的,需要对程序进行修正。
    |--Exception:异常,可以有针对性的处理方式

无论是错误还是异常,它们都有具体的子类体现每一个问题,它们的子类都有一个共性,就是都以父类名才作为子类的后缀名。

这个体系中的所有类和对象都具备一个独有的特点;就是可抛性。
可抛性的体现:就是这个体系中的类和对象都可以被throws和throw两个关键字所操作。
------------------------------------------------------
class  ExceptionDemo{
    public static void main(String[] args) {
//        byte[] buf = new byte[1024*1024*700];//java.lang.OutOfMemoryError内存溢出错误
    }
}
------------------------------------------------------
  在开发时,如果定义功能时,发现该功能会出现一些问题,应该将问题在定义功能时标示出来,这样调用者就可以在使用这个功能的时候,预先给出处理方式。
  
  如何标示呢?通过throws关键字完成,格式:throws 异常类名,异常类名...
  这样标示后,调用者,在使用该功能时,就必须要处理,否则编译失败。

   处理方式有两种:1、捕捉;2、抛出。
  对于捕捉:java有针对性的语句块进行处理。
try {
    需要被检测的代码;
}
catch(异常类 变量名){
    异常处理代码;
}
fianlly{
    一定会执行的代码;
}
--------------------------------------------------------
catch (Exception e) { //e用于接收try检测到的异常对象。
    System.out.println("message:"+e.getMessage());//获取的是异常的信息。
    System.out.println("toString:"+e.toString());//获取的是异常的名字+异常的信息。
    e.printStackTrace();//打印异常在堆栈中信息;异常名称+异常信息+异常的位置。
}
---------------------------------------------------------
异常处理原则:功能抛出几个异常,功能调用如果进行try处理,需要与之对应的catch处理代码块,这样的处理有针对性,抛几个就处理几个。

特殊情况:try对应多个catch时,如果有父类的catch语句块,一定要放在下面。

throw 和throws关键字的区别:
throw用于抛出异常对象,后面跟的是异常对象;throw用在函数内。
throws用于抛出异常类,后面跟的异常类名,可以跟多个,用逗号隔开。throws用在函数上。

通常情况:函数内容如果有throw,抛出异常对象,并没有进行处理,那么函数上一定要声明,否则编译失败。但是也有特殊情况。

异常分两种:
 1:编译时被检查的异常,只要是Exception及其子类都是编译时被检测的异常。
 2:运行时异常,其中Exception有一个特殊的子类RuntimeException,以及RuntimeException的子类是运行异常,也就说这个异常是编译时不被检查的异常。

编译时被检查的异常和运行时异常的区别:
 编译被检查的异常在函数内被抛出,函数必须要声明,否编译失败。
 声明的原因:是需要调用者对该异常进行处理。
 运行时异常如果在函数内被抛出,在函数上不需要声明。
 不声明的原因:不需要调用者处理,运行时异常发生,已经无法再让程序继续运行,所以,不让调用处理的,直接让程序停止,由调用者对代码进行修正。

定义异常处理时,什么时候定义try,什么时候定义throws呢?
  功能内部如果出现异常,如果内部可以处理,就用try;
  如果功能内部处理不了,就必须声明出来,让调用者处理。

自定义异常:当开发时,项目中出现了java中没有定义过的问题时,这时就需要我们按照java异常建立思想,将项目的中的特有问题也进行对象的封装。这个异常,称为自定义异常。

  对于除法运算,0作为除数是不可以的。java中对这种问题用ArithmeticException类进行描述。对于这个功能,在我们项目中,除数除了不可以为0外,还不可以为负数。可是负数的部分java并没有针对描述。所以我们就需要自定义这个异常。

自定义异常的步骤:
 1:定义一个子类继承Exception或RuntimeException,让该类具备可抛性。
 2:通过throw 或者throws进行操作。

异常的转换思想:当出现的异常是调用者处理不了的,就需要将此异常转换为一个调用者可以处理的异常抛出。

try  catch  finally的几种结合方式:
1,        2            3
try        try        try
catch        finally        catch
finally

这种情况,如果出现异常,并不处理,但是资源一定关闭,所以try  finally集合只为关闭资源。
记住:finally很有用,主要用户关闭资源。无论是否发生异常,资源都必须进行关闭。
System.exit(0); //退出jvm,只有这种情况finally不执行。

当异常出现后,在子父类进行覆盖时,有了一些新的特点:
  1:当子类覆盖父类的方法时,如果父类的方法抛出了异常,那么子类的方法要么不抛出异常要么抛出父类异常或者该异常的子类,不能抛出其他异常。
  2:如果父类抛出了多个异常,那么子类在覆盖时只能抛出父类的异常的子集。

注意:
   如果父类或者接口中的方法没有抛出过异常,那么子类是不可以抛出异常的,如果子类的覆盖的方法中出现了异常,只能try不能throws。
   如果这个异常子类无法处理,已经影响了子类方法的具体运算,这时可以在子类方法中,通过throw抛出RuntimeException异常或者其子类,这样,子类的方法上是不需要throws声明的。

常见异常:
1、脚标越界异常(IndexOutOfBoundsException)包括数组、字符串;
  空指针异常(NullPointerException)
2、类型转换异常:ClassCastException
3、没有这个元素异常:NullPointerException
4、不支持操作异常;
异常要尽量避免,如果避免不了,需要预先给出处理方式。比如家庭备药,比如灭火器。
/*创建线程的两种方式
 * 1、extends Thread   覆盖run()方法 run方法中描述的是自定义线程的运行任务   直接创建对象线程,就能开启线程
 *                       有多个线程,就需要多个对象,一定要覆盖run()  ,不然就没有线程运行的任务
 * 2、implements Runnable
 *          a:覆盖run();
 *          b: 创建一个对象 T t=new T();
 *                      Thread thread=new Thread(t);//Thread(Runnable target)
 *                      Thread thread1=new Thread(t,"xixi");
 *                      Thread thread2=new Thread(t,"hha");
 *                      Thread thread3=new Thread(t,"xixi");
 *                      //Thread(Runnable target,String name)
 *          
 *          Thread th=Thread.currentThread();//获得当前线程  current(当前的,最近的)
 *          String name=th.getName();//获得当前线程的名字
 *
 */
public class Thread_05 {

    /*
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        T t=new T();
        t.start();
        while(true){
            System.out.println("我我我我我我问WOW我我为我 ");
        }
    }

}
    class T extends Thread{
    public void run(){
    while(true){
        System.out.println("haha ");
    }
    }        
}
*/
    /*
     * extends Thread 创建多线程
     */
    /*
        public static void main(String[] args){
            new TicketWindow().start(); //创建线程对象并开启
            new TicketWindow().start();
            new TicketWindow().start();
            new TicketWindow().start();
            new TicketWindow().start();
            
        }

    
}    
    
    class TicketWindow extends Thread{
        private int tickets=100;
        public void run(){
            Thread th=Thread.currentThread();// 获得当前线程
            String th_name=th.getName();//获得当前线程的名字
            while(tickets>0){
                System.out.println(th_name+"正在出售第"+tickets+"piao");
                tickets--;
            }
            
        }
    }
    */

    /*
     * implements Runnable
     */
    /*
    public static void main(String[] args){
        TicketWindow t=new TicketWindow();//创建对象
        new Thread(t,"窗口1").start();//一个对象多个线程并开启
        new Thread(t,"窗口2").start();//创建线程的同时创建线程名称
        new Thread(t,"窗口3").start();
        new Thread(t,"窗口4").start();
        
    }
}
class TicketWindow implements Runnable{
    private static int tickets=100;
    public void run(){
        Thread th=Thread.currentThread();
        String th_name=th.getName();
        while(tickets>0){
            System.out.println(th_name+"正在出售"+tickets);
            tickets--;
        }
        
    }
    
}
    
    */
    /*
    
        public static void main(String[] args){
            //判断main线程是否为后台线程,Thread.currentThread().isDaemon(),当前线程为main线程
            System.out.println("main线程是后台线程吗?"+Thread.currentThread().isDaemon());
            DaemonThread dt=new DaemonThread();
            Thread t=new Thread(dt,"后台线程");
            System.out.println("t线程是默认为后台线程吗?"+t.isDaemon());
            //将t线程改为后台线程
            t.setDaemon(true);//确定设置为后台线程
            t.start();//t线程开启
            for(int i=1;i<=10;i++)
                System.out.println(i);
            
        }
            
    
}
    //后台线程,线程分为前台线程跟后台线程,如果只剩下了后台线程,那么进程会结束
    //设置线程为后台线程  setDaemon(),需要在线程启动前设置为后台线程thread.setDaemon()
class DaemonThread implements Runnable{
    public void run(){
        while(true){
            System.out.println(Thread.currentThread().getName()+"正在运行");
        }
    }
}
    
    */
    /*线程有5种状态:
     * a:新建状态   :就是创建了一个线程,JVM为其分配了内存空间
     * b、就绪状态:线程调用了start(),开启了线程,但是还没有获得Cpu的使用权
     *                 多线程其实是Cpu快速地在多个线程之间切换,在某个时间点仅仅能执行某一个线程
     * c:执行状态: 线程获得了Cpu的使用权,线程就进入了执行状态,在某个时间片后就会切换出来,
     *                 只是这个时间片十分的短,短的让人感觉不到
     * d:阻塞:是指执行状态下的线程因为某些特殊原因,放弃了Cup的执行权,进入了阻塞的状态,从阻塞状态
     *             出来后会进入就绪状态
     *             执行————→阻塞:1、sleep(long time);    等其自动睡醒,会自动进入就绪状态
     *                         2、当线程获取对象的同步锁时,同步锁被其他的线程占着,所以就会进入
     *                             阻塞状态,必须等到其他线程释放了同步锁时,才会从阻塞状态进入就绪状态
     *                                 等待同步锁
     *                         3、wait(); 调用wait()方法,需要线程notify()唤醒线程
     *                         4、当在一个线程中调用了另一个线程的join()——-等待该线程结束
     *                         5、yield()    暂停当前执行的线程,执行其他线程
     *                         6、调用了阻塞的IO方法
     * e:死亡状态:  正常执行完或者出现Exception或Error
     */
    
    
}
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
   
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值