Java基础---异常,包

异常

1.定义

异常指的是在程序运行过程中发生的异常事件,通常是由硬件问题或者程序设计问题所导致的。在Java等面向对象的编程语言中异常属于对象。

Java异常类层次结构图:
这里写图片描述

2.异常由来:

编程中对于那些会出现的问题,Java采用异常机制来解决。
最常使用的就是try{}catch{}

本质:java对不正常情况进行描述后的对象体现。
程序可能出现的错误或问题:
    a、用户输入错误导致的异常:如用户不正常使用程序,输入一些非法参数
    b、设备硬件等发生的错误:如硬盘损坏等
    c、物理限制:如存储空间不足等
    d、代码错误:在程序编写的方法可能不正确,数组越界,返回错误参数等。

3.异常体系

Throwable 类

是 Java 语言中所有错误或异常的超类。只有当对象是此类(或其子类之一)的实例时,才能通过 Java 虚拟机或者 Java throw 语句抛出。类似地,只有此类或其子类之一才可以是 catch 子句中的参数类型。 

有两个重要的子类:Exception(异常)和 Error(错误)

Error(错误)

是程序无法处理的错误,表示运行程序中较严重的问题。
这些错误表示故障发生于虚拟机自身、或者发生在虚拟机试图执行应用时,如Java虚拟机运行错误(Virtual MachineError)、类定义错误(NoClassDefFoundError)等。这些错误是不可查的,因为它们在应用程序的控制和处理能力之 外,而且绝大多数是程序运行时不允许出现的状况。对于设计合理的应用程序来说,即使确实发生了错误,本质上也不应该试图去处理它所引起的异常状况。在 Java中,错误通过Error的子类描述。

Exception(异常)

是程序本身可以处理的异常。
RuntimeException类是他的一个比较特殊的类。

RuntimeException 类:
    RuntimeException 类及其子类表示“JVM 常用操作”引发的错误。例如,若试图使用空值对象引用、除数为零或数组越界,则分别引发运行时异常(NullPointerException、ArithmeticException)和 ArrayIndexOutOfBoundException。 

注意:异常和错误的区别:异常能被程序本身处理,错误是无法处理。

4.异常分类

1.Java的异常
Java的异常(包括Exception和Error)分为可查的异常(checked exceptions)和可不查的异常(unchecked exceptions)。

可查异常(编译器要求必须处置的异常):

 程序在运行时,在一定程度上可以预知的异常,并可以采取某种方式进行处理。
 除了RuntimeException及其子类以外,其他的Exception类及其子类都属于可查异常。这种异常的特点是Java编译器会检查它,也就是说,当程序中可能出现这类异常,要么用try-catch语句捕获它,要么用throws子句声明抛出它,否则编译不会通过。

可不查异常(编译器不要求强制处置的异常):

包括运行时异常(RuntimeException与其子类)和错误(Error)。
这类异常编译时,编译器不会去检查。

2.Exception异常

Exception 这种异常分两大类运行时异常和非运行时异常(编译异常)。程序中应当尽可能去处理这些异常。

运行时异常:

RuntimeException及其子类,如NullPointerException(空指针异常)、IndexOutOfBoundsException(下标越界异常)等。这些异常编译器不检查,即使不使用try-catch捕获,或使用throws抛出,编译器也不会报错,但会在运行时触发。
这些异常一般出在逻辑上,在程序设计时应该从逻辑角度尽可能避免这类异常。

非运行时异常 (编译异常):

除RuntimeException及其子类外的异常,类型上属于Exception类及其子类。
编译器会检查此类一场,如果不处理,程序是无法编译通过的。

总结:根据编译器是否检查来进行划分。
总的来说,RuntimeException及其子类外的异常编译器不进行检查,其他Exception都需要处理。

异常处理

对于运行时异常、错误或可查异常,Java技术所要求的异常处理方式有所不同:

 a.运行时异常:java允许可以不抛出,不捕获;运行时由系统由系统抛出。
 b.Error,不抛出,不捕获,因为Error是java所不允许发生的。
 c.可查行异常,必须捕获或者抛出。

一个方法所能捕捉的异常,一定是Java代码在某处所抛出的异常。简单地说,异常总是先被抛出,后被捕捉的。

异常处理有两种方式:捕捉异常(try-catch),抛出异常(throws)

1.捕捉异常

java提供了特有的语句进行处理:
try

    {

             需要被检测的代码。

    }

    catch(异常类  变量)

    {

             处理异常的代码;(处理方式)

    }

    finally

    {

             一定会执行的语句;

    }

注意:

    1)finally中定义的通常是关闭资源代码。因为资源必须释放。

    2)如果在一个功能中,定义了一些必须要执行的代码,可以用try{}finally{}的方式,将一定执行的代码放在finally代码块中。

    3)finally只有一种情况不会执行。当执行到System.exit(0);fianlly不会执行。
    public static void main(String[] args) {
        int a = 6;
        int b = 0;
        try {
            System.out.println("a/b的值是:"+ a / b);
        } catch (ArithmeticException e) {
            System.out.println("程序出现异常,变量b不能为0。");
        }
        System.out.println("程序正常结束。");
    }
}

分析:此例中由try中监控区,检测到“除数为0”从而引发ArithmeticException异常,由异常处理器catch捕获,并处理。
但是,实际上,”除数为0“ArithmeticException异常是RuntimeException子类,会由系统自动抛出,不需要使用throw语句。

需要注意的是,一旦某个catch捕获到匹配的异常类型,将进入异常处理代码。一经处理结束,就意味着整个try-catch语句结束。其他的catch子句不再有匹配和捕获异常类型的机会。
对于有多个catch子句的异常程序而言,应该尽量将捕获底层异常类的catch子 句放在前面,同时尽量将捕获相对高层的异常类的catch子句放在后面。否则,捕获底层异常类的catch子句将可能会被屏蔽。
这里写图片描述

小结:

try 块:用于捕获异常。其后可接零个或多个catch块,如果没有catch块,则必须跟一个finally块。
catch 块:用于处理try捕获到的异常。

finally块:无论是否捕获或处理异常,finally块里的语句都会被执行。当在try块或catch块中遇到return语句时,finally语句块将在方法返回之前被执行。在以下4种特殊情况下,finally块不会被执行:
1)在finally语句块中发生了异常。
2)在前面的代码中用了System.exit()退出程序。
3)程序所在的线程死亡。
4)关闭CPU。

2.抛出异常

可以通过throws和throw抛出异常。
1)throws
定义:

 如果一个方法可能会出现异常,但没有能力处理这种异常,可以在方法声明处用throws子句来声明抛出异常。例如汽车在运行时可能会出现故障,汽车本身没办法处理这个故障,那就让开车的人来处理。

throws语句用在方法定义时声明该方法要抛出的异常类型,如果抛出的是Exception异常类型,则该方法被声明为抛出所有的异常。多个异常可使用逗号分割。throws语句的语法格式为:

methodname throws Exception1,Exception2,..,ExceptionN  
{  
}  

方法名后的throws Exception1,Exception2,…,ExceptionN 为声明要抛出的异常列表。当方法抛出异常列表的异常时,方法将不对这些类型及其子类类型的异常作处理,而抛向调用该方法的方法,由他去处理。例如:

import java.io.*;

public class Test1 {

    public static void method() throws IOException {
        File f = new File("r:\\");
    }

    public static void main(String[] args) {
        //此处报错,Unhandled exception type IOException未处理异常
        method();
    }

}

原因:IOException是Exception子类,是编译异常,必须捕获,method()方法使用throws向上层调用(main函数)抛出了,但是main函数未处理,所以造成了错误。
解决:使用try-catch捕获并处理。
Throws抛异常的原则:

    1)不可查异常(unchecked exception)RuntimeException和Error异常可以不抛出,但是可查异常(checked exception)必须被抛出或者被捕获,否则编译会报错。

    2)仅当抛出了异常,该方法的调用者才必须处理或者重新抛出该异常。当方法的调用者无力处理该异常的时候,应该继续抛出,而不是囫囵吞枣。
public class Test1 {

    void method() throws IOException {
        File f = new File("r:\\");
    }

    // 编译错误,必须捕获或者声明IOException
    void method1() {
        method();
    }

    // 合法,声明抛出了IOException
    void method2() throws IOException {
        method();
    }

    // 合法,声明抛出Exception,IOException是Exception的子类
    void method3() throws Exception {
        method();
    }

    // 合法,捕获了IOException
    void method4() {
        try {
            method();
        } catch (IOException e) {
        }
    }

    // 不合法,又抛出了一个IOException,必须抛出或者再次捕获
    void method5() {
        try {
            method();
        } catch (IOException e) {
            throw new IOException();
        }
    }

    // 合法,再次抛出的新的异常
    void method6() throws Exception {
        try {
            method();
        } catch (IOException e) {
            throw new Exception();
        }
    }
}
        3)在子父类覆盖时:
          a,子类抛出的异常必须是父类的异常的子类或者子集。
          b,如果父类或者接口没有异常抛出时,子类覆盖出现异常,只能try不能抛。
class T1 {
    void method() throws IOException {
    }
}
class T2 extends T1{
//错误,子类抛出的异常不是父类抛出异常的子类
    void method()throws Exception {
    }
}

2)throw抛出异常
在函数体内使用,即抛出一个一场对象。形如:

throw new Throwable();

该对象是人为抛出的,虽然和程序运行产生的不同,但是仍是需要抛出或者捕获的。

Throwable

Throwable中的方法:

1.getMessage():获取异常信息,返回字符串。
2.toString():获取异常类名和异常信息,返回字符串。
3.printStackTrace():获取异常类名和异常信息,以及异常出现在程序中的位置,返回值void。
4.printStackTrace(PrintStreams):通常用该方法将异常内容保存在日志文件中,以便查阅。

自定义异常:

/***
 * 自定义异常
 */
class Demo{
    //除法,抛出我的自定义异常
    int div(int a, int b) throws MyException{
        if(b==0){
            throw new MyException("除数不能为负数!");
        }
        return a/b;
    }
}
public class Test3 {

    public static void main(String[] args) {
        int a = 10;
        int b = 0;
        try {
            Demo d = new Demo();
            int s = d.div(a, b);
        } catch (MyException e) {
            // TODO: handle exception
            e.printStackTrace();
            System.out.println(e.getMessage());
        }
    }
}

class MyException extends Exception {
    /***
     * 自定义异常的构造方法,信息的传递通过有参构造方法,
     *  父类通过有参构造方法传递的参数来打印消息
     */
    public MyException(String MyMessage) {
        super(MyMessage);
    }
}

小测试:

import java.util.*;

/***
 *  老师使用电脑讲课。
 * 
 *         描述电脑: 1、电脑运行 2、电脑重启 描述电脑问题: 1、电脑蓝屏了 2、电脑起火了
 * 
 *         描述老师: 1、老师使用电脑 2、老师讲课。
 * 
 *         描述老师可能出现的问题: 
 *         1、老师不能继续讲课了。
 *         2.电脑蓝屏,重新启动 
 *                  a.多次重启后,成功 
 *                  b.多次蓝屏重启后,电脑着火了
 *         3.一次启动成功,老师开始讲课
 */
//蓝屏异常
class BlueScreenException extends Exception {
    public BlueScreenException(String message) {
        super(message);
    }
}

//电脑着火
class FireBreakException extends Exception {
    public FireBreakException(String message) {
        super(message);
    }
}
//电脑类
class Computer {
    // 随机产生一个数,来模拟电脑启动
    int i;
    //启动
    void run() throws BlueScreenException, FireBreakException {
        i = (int) (Math.random()*3+1);
        if(1==i)
        {
            System.out.println("电脑正常启动");
        } else if(2==i)
        {
            throw new BlueScreenException("电脑蓝屏了!");//蓝屏异常
        } else
        {
            throw new FireBreakException("电脑着火了!");//着火异常
        }
    }
    //重启
    void reset() {
        System.out.println("电脑重新启动");
        try {
            run();
        } catch (BlueScreenException e) {
            System.out.println(e.getMessage());
            reset();
        } catch (FireBreakException e) {

            System.out.println("多次重启,着火了!");
        }
    }
}

//无法上课的异常
class BreakTeachingException extends Exception{
    public BreakTeachingException(String message){
        super(message);
    }
}


//老师类
class Teacher{
    private Computer c = new Computer();
    void teach() throws BreakTeachingException{
        try {
            c.run();
            System.out.println("老师开始上课!");
        } catch (BlueScreenException e) {

            System.out.println(e.getMessage());
            c.reset();
        } catch (FireBreakException e) {

            throw new BreakTeachingException("老师无法上课,原因"+e.getMessage());
        }
    }
}
public class Test4 {
    public static void main(String[] args) {
        Teacher t = new Teacher();
        try {
            t.teach();
        } catch (BreakTeachingException e) {

            e.printStackTrace();
            System.out.println("暂停上课,电脑着火了!");
        }
    }
}

一次启动成功,老师开始讲课:
这里写图片描述
一次启动,电脑着火:
这里写图片描述
多次蓝屏重启后成功
这里写图片描述
多次蓝屏重启后电脑着火
这里写图片描述

确保类的唯一性,使得同类名的类可以同时存在,使用包进行划分。
权限问题:
这里写图片描述

规则

    1、包必须写在程序的第一行。因为要先有包,才知道类文件的存放地方。

    2、类的全称:包名.类名。

    3、编译定义了包的程序文件时,在编译时要指定包的存储目录。

   如:javac –d c:\mypack类名.java

jar包

创建jar包

            jar  -cvf  mypack.jar packa packb

查看jar包

            jar  -tvf  mypack.jar  [>定向文件]

解压缩

            jar  -xvf  mypack.jar

自定义jar包的清单文件

            jar –cvfm  mypack.jar mf.txt  packa packb

单个包打成jar包:

这里写图片描述

进入cmd:
这里写图片描述

编译:
这里写图片描述
javac -d . Demo.java和javac -d f:\JavaDemo Demo.java的不同在于指定的目录不同。

jar包生成:
这里写图片描述

运行:把生成的jar包放到D盘下,设置classpath路径,并运行。
这里写图片描述

多个不同包下的类建jar包:
同理:javac –d . Demo.java分别编译
这里写图片描述
建好后:
这里写图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值