JAVA--高级基础开发

原创
2019/11/12 17:28
阅读数 177

Day02【异常、线程】

  • 异常

1.1异常的概念:

  1. 异常: 指的是程序在执行过程中,出现的非正常的情况。最终会导致的JVM的正常停止。
  2. 异常本身就是一个类,产生异常就是创建异常对象并抛出了一个异常对象,java处理异常的方式,就是中断处理。
  1. 异常:指的并不是语法错误,编译不通过,不能产生字节码文件,程序根本无法正常运行。
  2. 编写一个良好的程序,应该避免异常发生从而终止整个程序,而是通过一定的技术来捕获异常并且能够处理好,让程序继续运行。
  3. Java这门语言,本身就有处理异常的能力,我们学习的就是怎么掌握去处理异常的能力。
  4. Java异常的处理:其实是5个关键字: try 、catch 、throw 、throws 、finally

1.2 异常的原理

  1. 抛出异常: 当程序运行期间,如果发生了异常,会自动的产生一个相应的异常类对象,并且会自动把这个异常类对象交给jvm,这个过程就是就是抛出异常。
  2. 捕获并处理:jvm接收到异常类对象时,会自动的寻找有没有相应的代码能够处理该异常,如果存在能够处理该异常的代码,则把异常让其捕获并处理,如果没有找到相应的代码,jvm会终止,程序退出。

1.3异常体系的分类

  1. 异常的处理机制就是帮助我们找到程序中的问题,异常的根类是:java.lang.Throwable.

他底下有两个子类:java.lang.Error与java.lang.Exception.我们平常所说的异常,值的就是:java.lang.Exception.

  1. Throwable 体系:
  1. Error: 严重的错误,无法通过处理的错误,只能事先避免,比如绝症。例如:服务器宕机,jvm内部出错。服务器资源耗尽。
  2. Exception: 表示异常,当异常出现后,程序猿或者攻城狮能够通过代码方式去及时纠正,使程序继续运行,是必须要处理的。
  3. 程序猿能够处理的只有Exception,对Error 无能为力。
    1. Exception
    2. Exception根据异常的功能分为:受检异常和非受检异常。
    3. 受检异常:指的就是程序在编译期间需要处理的异常。(javac 编译期间异常)
    4. 非受检异常: 程序在运行期间需要处理的异常。(java 运行期间的异常)
  • 数组下标越界。
  • 除数为零。ArithmeticException
  • java.lang.RuntimeException 是所有非受检异常的父类

1.5Throwable的常用方法

  1. public void printStackTrace():打印异常的详细信息.
  • 包含了异常的原因,异常的类型,还包括异常出现的位置。,在开发和调试阶段都得使用 printStackTrace()方法。
  1. Public  String  getMessage();获取异常发生的原因。提示给用户的时候,就提示异常发生的原因。
  2. public String  toString():获取异常的类型和异常描述信息(不经常使用)
  • 异常的处理
    1. 捕获异常 try..catch
  1. 当异常出现的时候,程序会立刻终止,我们的及时捕获并处理异常。
  1. 在使用方法中我们使用try…..catch 来捕获处理异常。
  2. Try..catch 的方式就是来捕获并处理异常,
  3. 捕获异常:java 中对异常有针对性的语句进行捕获,可以对出现的异常进行指定方式的处理。【很有针对性的去捕获并处理】。

2法格式:

Try{

//编译期间可能要出现异常的代码

}catch(异常类型  异常对象){

   /打印异常的代码

  /打印异常的信息

}

解析:try: 该代码块中编写可能产生异常的代码。

      Catch: 用来进行某种异常的捕获,实现对异常捕获的处理,

Try和catch 不能单独使用,必须结合使用。

public class Test0 {

    public static void main(String[] args) {

        int  aa=10;

        int  bb=0;

        try{

            int  cc=aa/bb;

            System.out.println(cc);

         }catch (ArithmeticException ce){

            ce.printStackTrace();

        }

        System.out.println("执行了吗??");

 

    }

}

 

通过以上程序我们发现,catch 只能处理try中所对应的异常类型,如果发生的异常和catch不匹配。则是无法处理的。因此try 后面可以有多个catch出现,每个catch处理不同的异常的类型。

public class Test0 {

    public static void main(String[] args) {

        int  aa=10;

        int  bb=0;

        int[]sum={1,2,3,4};

        try{

            int  cc=aa/bb;

            //数组下标越界://java.lang.ArrayIndexOutOfBoundsException

            System.out.println(sum[4]);

           System.out.println(cc);

         }catch (ArithmeticException ce){

            ce.printStackTrace();

        }catch (ArrayIndexOutOfBoundsException  ce){

            ce.printStackTrace();

        }

        System.out.println("执行了吗??");

 

    }

}

 

 

  1. 如果try中有多个异常存在,则那个异常先发生,发生后就直接去找对应的catch,

Catch执行完后,代码的顺序是继续从Catch往下执行的,不会返回try语句块中,所以try..catch 会帮我们捕获异常,但是会影响程序的正常的流程,最终我们还是要程序猿手动去处理发生的异常。

  1. 如果try下面有多个catch,catch中的异常类型如果是异常的父类,那么他只能位于最后一个catch中。
    1. finally
  1. finally: 有一些特定的代码,无论异常是否发生,都要去执行,另外,异常会引起程序的跳转,导致有些代码执行不到,而finally 就是解决这个问题,finally 语句块中存放的代码,一定会被执行到的。
  2. 那么什么时候的代码必须最终执行:
  • 当我们在 try 语句块中使用到了一些物理资源(磁盘文件、网络连接、数据库连接等对象时),我们都得在使用完之后,最终关闭这些对象,来释放它们所占的内存资源。
  1. Finally的语法:
  1. Try….catch…..finally.
  2. Finally 也不能单独使用。

 

      try{

            System.out.println(10/0);

        }catch (ArrayIndexOutOfBoundsException  ce){

            ce.printStackTrace();

        }finally {

            System.out.println("不管上面的异常是否执行,finall永远执行!!");

        }

    }

    1. 抛出异常
  1. 在编写程序时,我们必须要考虑程序出现问题的情况。比如,在定义方法时,方法需要接收参数,那么,当调用方法时传递参数,那么在方法中首选需要对参数进行合法的判断,数据若不合法,就应该告诉调用者,传递合法的数据进来。这时需要使用抛出异常的方式来告诉调用者。
  2. 在 Java 中,提供了一个 throw 关键字,用来抛出一个指定的异常对象?那么抛出异常对象后,我们如何操做呢????
  1. 创建一个异常类对象,封住一些提示的信息。
  2. 需要将这个异常对象告知调用者,那么怎么才能告知调用者呢?怎么将这个异常对象传递到调用者处。那么我们通过throw 关键字就可以完成。
  3. 语法:throw  new 异常类(“要提示的信息”);
  4. Throw用在方法内,用来抛出一个异常类对象,这个异常对象传递到调用者处,并结束当前方法的执行。

例如:

1.throw new ArithmeticException(“除数不能为零”);

2.throw new ArrayIndexOutOfBoundsException(“数组下标越界”);

5.

/throw 抛出异常

public class Test2 {

    public static void main(String[] args) {

        int[]num={1,2,3,4,5,6,7};

        int  index=10;

        getSting(num,index);

    }

public  static  void  getSting(int[]num,int index){

//判断条件,如果满足,当执行完 throw 抛出异常对象后,方法已经无法继

续运行,这时就会结束当前方法的执行,并将其异常告知给调用者,这就是需要通

过异常来解决

 if(index<0||index>num.length){

            throw  new ArrayIndexOutOfBoundsException("主人数组的下标太大的");

//System.out.println("ha"); //位于 throw new 下面的代码不会被执行,报错

        }else{

            System.out.println(num[index]);

        }

    }

}

//运行的结果:Exception in thread "main"

// java.lang.ArrayIndexOutOfBoundsException: 主人数组的下标太大的

【注意】如果产生了异常,我们就会将异常抛出,也就是将问题返回给该方法的调用者,那么对于调用者来说,一种就是进行捕获处理,另一种就是继续将异常抛出去,使用throw来声明。

    1. 声明异常throws
  1. 声明异常: 就是将问题标识出来,报告给调用者,如果方法内通过throw 抛出了编译时(受检)异常,而没有捕获处理,那么必须通过throws 来进行声明,让调用者自己去处理。
  2. 关键字throws 用于方法上来声明一个异常,用于表示当前的方法不处理异常,而是提醒该方法的调用者来处理异常。
  3. 声明异常的格式:

[访问修饰符]  返回值类型  方法名(参数列表) throws  异常类名1….异常类2{

      //代码块

}

【注意】:throws只能用于方法的签名的后面,而throw 只能用于方法体中。

    1. 异常实践
  1. 尽量减少try语句块的体积,因为try中每句代码的执行都需要判断有没有异常发生,影响了代码执行的效率。
  2. 运行时异常被抛出可以不处理,即不捕获也不声明,但是如果是受检(编译)异常被抛出,必须处理,一种throws来进行声明,另一种是利用 try….catch() 来进行捕获并处理。
  3. 如果父类抛出 了多个异常,子类重写父类的该方法时,只能抛出相同的异常或异常的子类。
  4. 父类方法没有抛出异常,子类重写父类的该方法时,也不可以抛出异常,此时如果子类产生异常,只能声明并处理,不能声明抛出。
  5. 在开发和调式阶段,建议吧异常的信息打印处理,方便解决问题。
      1.  

练习题:要求:

我们模拟登录操作,如果用户名已存在,则抛出异常并提示:该用户名已被注册。

a)首选自定义一个登录异常类 LoginException

b)模拟登录操作,使用数组或者 ArrayList 模拟数据库中存储的数据,并且提供当前注册账号是否存在的方法用于判断。

//自定义一个异常类

public class LoginException extends Exception{

    public LoginException() {

    }

 

    public LoginException(String message) {

        super(message);

    }

 

    public LoginException(String message, Throwable cause) {

        super(message, cause);

    }

 

    public LoginException(Throwable cause) {

        super(cause);

    }

 

    public LoginException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {

        super(message, cause, enableSuppression, writableStackTrace);

    }

}

 

public class Login {

    static String[]stuName={"liwenjie","zhangsan","李文杰","桑凤娇","郭朝旭"};

 

    public static void main(String[] args){

        Scanner input=new Scanner(System.in);

        System.out.println("请输入用户名");

        String  userName=input.next();

        try{

            boolean flag=display(userName);

            if(flag){

                System.out.println("用户注册成功");

            }

        }catch (Exception  ce){

            ce.printStackTrace();

        }

    }

    public static boolean display(String name)throws Exception{

        for(String  ss:stuName){

            if(ss.equals(name)){

                //抛出一个异常

                throw new LoginException("用户名已被注册过!!!");

            }

        }

        return true;

    }

}

 

 

//集合版的模拟登录系统

public class Student{

    public static void main(String[] args) {

        Scanner  input=new Scanner(System.in);

        System.out.println("请输入用户名:");

        String username=input.next();

        try{

            boolean flag=meth(username);

            if(flag){

                System.out.println("注册成功");

            }

        }catch (Exception  ce){

            ce.printStackTrace();

        }

    }

    public  static boolean meth(String  name)throws Exception{

        ArrayList<String>list=new ArrayList<>();

        list.add("sangfengjiao");

        list.add("liwnejie");

        list.add("mashitian");

        list.add("赵云");

        list.add("zhangsan");

        for(String ss:list){

            if(ss.contains(name)){

                throw  new LoginException("用户名已被注册过!!!");

            }

        }

        return true;

    }

}

2.6 3. 自定义异常类

每一个学生(Student)都有学号,姓名和分数,分数永远不能为负数。如果老师给学生赋值一个负数,抛出一个自定义异常。

 

//自定义异常类

public class Student2 {

    private  String  stuName;

    private Integer  stuXue;

    private Double   stuScore;

    public Student2(){

 

    }

    public Student2(String stuName,Integer stuXue,Double stuScore){

        this.stuName=stuName;

        this.stuXue=stuXue;

        this.stuScore=stuScore;

    }

 

    public String getStuName() {

        return stuName;

    }

 

    public void setStuName(String stuName) {

        this.stuName = stuName;

    }

 

    public Integer getStuXue() {

        return stuXue;

    }

 

    public void setStuXue(Integer stuXue) {

        this.stuXue = stuXue;

    }

 

    public Double getStuScore() {

        return stuScore;

    }

 

    public void setStuScore(Double stuScore){

        if(stuScore<0){

            throw new  StudentScore("分数不能为负数!!!!");

        }else{

            this.stuScore = stuScore;

        }

 

    }

}

public class StudentScore  extends RuntimeException{

    public StudentScore() {

    }

 

    public StudentScore(String message) {

        super(message);

    }

 

    public StudentScore(String message, Throwable cause) {

        super(message, cause);

    }

 

    public StudentScore(Throwable cause) {

        super(cause);

    }

 

    public StudentScore(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {

        super(message, cause, enableSuppression, writableStackTrace);

    }

}

public class Stundent3 {

    public static void main(String[] args) {

        //创建Student对象

        Student2  ss=new Student2();

        ss.setStuName("李文杰");

        //抛出:day02.StudentScore: 分数不能为负数!!!!

        ss.setStuScore(-100.0);

        ss.setStuXue(33);

        System.out.println(ss.getStuName());

        System.out.println(ss.getStuScore());

        System.out.println(ss.getStuXue());

    }

}

 

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部