零基础学习之Java异常

  • 概述
  • 基本介绍
    • Error
      • 代码示例
    • Exception
      • 代码示例
  • 异常的处理
    • throw
      • 代码示例
    • throws
      • 代码示例
    • try…catch
      • 代码示例
  • finally块
    • 代码示例
    • finally与return(面试)
      • 形式一:从try回来
      • 形式二:从catch回来
      • 形式三:从finally回来
  • 自定义异常
    • 基本介绍
    • 代码示例
  • 异常注意事项

概述

正如“人无完人”一样,程序也不是完美的,它总会存在这样那样的问题,而有些问题并不是能够通过程序员开发更好的代码来解决的,如果我们忽视它,可能就会造成程序的终止,甚至是系统的崩溃。因此,我们需要想办法来合理的解决它,这就是Java中异常的由来。

异常是指程序在执行过程中,出现的非正常情况。比如:空的引用、数组下标越界、内存溢出错误、读取文件不存在、网络断开等

一般来说有两种方法来处理异常:

  • 遇到错误就终止程序运行;
  • 开发人员在编写程序的时候考虑到可能出现的非正常情况,提前做好处理(这个是最好的,不过也是不容易的);

那究竟异常有哪些?常见的处理方法是什么?我想通过下面的文章,你一定可以得到想要的答案!

基本介绍

在Java这样一个面向对象的语言中,异常被当成了一个对象来处理。其根类是java.lang.Throwable类,Throwable类有分成了两个类,即Error和Exception。这是异常的两个大类,他们分别代表了两种情况:

  • Error:不能处理的错误,这是系统内部的错误,运行时报错,属于系统问题。一般发生这种异常,JVM会选择终止程序,开发人员需要提前避免。
  • Exception:可以处理的异常,这是比较常见的异常,开发人员可以根据Java提供的类和问题对这类异常进行处理。


Error和Execption包括很多种情况,这才是我们需要考虑的,下面对它们进行分别介绍。

Error

对于严重错误Error,没有办法处理,只能做到提前避免。常见的Error有:StackOverflowError(内栈溢出错误)和OutOfMemoryError (内存溢出错误)。

代码示例

OutOfMemoryError

Java中堆是用来存储对象实例的,,因此如果我们不断地创建对象, 并且对象没有被垃圾回收, 那么当创建的对象过多时, 会导致 heap 内存不足, 进而引发 OutOfMemoryError 异常.

/**
* 内存溢出
*/public class Heap{public static void main(String[] args){//创建数组list,用来保存对象List<Integer> list = new ArryList<>();int i=0;while(true){//不断创建对象list.add(i++);}}
}

StackOverflowError
JVM 的运行时数据区中有一个叫做栈的内存区域, 此区域的作用是: 每个方法在执行时都会创建一个栈帧, 用于存储局部变量表、操作数栈、方法出口等信息。因此当创建一个无限递归的递归调用, 当递归深度过大时, 就会耗尽栈空间, 进而导致了 StackOverflowError 异常.

/**
* 栈溢出
*/public class Stack{public static void main(String[] args){//调用方法new Stack().test();}//创建测试方法public void test() {//自己调用自己(递归调用)test();}
}

Exception

一般来说,我们所说的异常就是指Exception,因为这类异常一旦出现,我们就要对代码进行更正,修复程序进行处理。根据在编译时期还是运行时期去检查异常,可以将Exception分为:

  • 编译时期异常:checked异常。在编译时期,就会检查,如果没有处理异常,则编译失败(开发工具会提示),如文件找不到异常等。
  • 运行时期异常:runtime异常。在运行时期,检查异常.在编译时期,运行异常不会被编译器检测到(不开发工具不会提示),如空指针异常,类型转换异常,数字操作异常,类型不匹配异常等。

代码示例

编译时异常这里就不举例了,在开发工具里会标红提示。下面是常见的运行时异常代码示例。

package com.atguigu.demo;import org.junit.Test;import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Scanner;public class Demo1 {/*编译时异常:必须进行处理,否则编译不通过*///文件找不到@Testpublic void test07()  {//这里FileInputStream报红,编译异常,需要处理FileInputStream fis = new FileInputStream("Java异常学习笔记.txt"); }/*运行时异常*/public static void main(String[] args) {//类型不匹配异常Scanner input = new Scanner(System.in);System.out.print("请输入一个整数:");//这个时获取控制台的输入,如果输入的不是整数,则报类型不匹配异常int num = input.nextInt();}//空指针异常@Testpublic void testNullPointerException() {String[] names = new String[5];System.out.println(names[0].length());//字符串的长度}//类型转换异常@Testpublic void testClassCastException() {Object obj = new Object();String str = (String) obj;}//数学操作异常异常@Testpublic void testArithmeticException(){int i = 1/0;}}

异常的处理

既然Java程序异常是非常常见的,那我们该如何处理它呢。由于Java将异常作为对象来处理,因此我们可以将Java异常的处理分成三个部分:

  • Java程序出现异常时会生成一个异常类对象,该异常对象将被提交给Java运行时系统,这个过程称为抛出(throw)异常。
  • Java程序出现异常时将问题标识出来,报告给调用者,让调用者去处理。这个过程通过throws进行声明。
  • Java程序出现异常时,在方法中使用try-catch的语句块来处理异常。

throw

Java程序出现异常时会生成一个异常类对象,该异常对象将被提交给Java运行时系统,这个过程称为抛出(throw)异常。异常对象的生成有两种方式:

  • 自动生成:程序运行过程中,虚拟机检测到程序发生了问题,如果在当前代码中没有找到相应的处理程序,就会在后台自动创建一个对应异常类的实例对象并抛出——自动抛出
  • 手动创建:Exception exception = new ClassCastException();——创建好的异常对象不抛出对程序没有任何影响,和创建一个普通对象一样,但是一旦throw抛出,就会对程序运行产生影响了。

使用格式:

throw new 异常类名(参数);

代码示例

package com.atguigu.demo;public class Demo2 {public static void main(String[] args) {//定义数组和访问的角标int[] arr = {1,2,3,4};int index = 4; //测试数组越界异常
//        int[] arr = {1,2,3,4}; //为null,测试空指针异常//调用方法测试int element = getElement(arr, index);System.out.println(element);}public static int getElement(int[] arr, int index) {//判断数组为空异常if (arr == null){throw new  NullPointerException("数组为空!");}//判断数组越界异常// 数组最大下标 arr.length-1if (index < 0 || index > arr.length -1){throw new ArrayIndexOutOfBoundsException("角标越界!");}int element = arr[index];return element;}
}

throws

Java程序出现异常时将问题标识出来,报告给调用者,让调用者去处理。这个过程通过throws进行声明。关键字throws运用于方法声明之上,用于表示当前方法不处理异常,而是提醒该方法的调用者来处理异常(如果调用者不处理,则接着抛出异常).(不主动处理的方式,甩锅给别人)

声明异常格式:

修饰符 返回值类型 方法名(参数) throws 异常类名1,异常类名2…{   }   //可以声明多个异常(也可直接一个Exception)

代码示例

package com.atguigu.demo;
/*声明异常*/
public class Demo4 {//声明一个Exception public static void main(String[] args) throws Exception {method();//不能直接调用,必须接着声明异常或者处理异常,否则编译不通过}//声明多个异常public static void method() throws NullPointerException,ArrayIndexOutOfBoundsException{System.out.println("声明异常!");}
}

try…catch

Java程序出现异常时,在方法中使用try-catch的语句块来处理异常。try-catch的方式就是捕获异常:Java中对异常有针对性的语句进行捕获,可以对出现的异常进行指定方式的处理。(主动处理的方式,不甩锅给别人)

捕获异常语法如下:

try{//可能会出现异常的代码放在这里
}catch(异常类型  e){//处理异常的代码//记录日志/打印异常信息/继续抛出异常
}catch(异常类型  e){//处理异常的代码//记录日志/打印异常信息/继续抛出异常
}
...

注意: try和catch都不能单独使用,必须连用(除非有finally,后面说)。
catch可以有好几个,即可以捕获几个异常

代码示例

package com.atguigu.demo;/*try catch 捕获异常*/
public class Demo5 {public static void main(String[] args) {//获取方法异常信息try {//正常执行代码add();} catch (Exception e) {//捕获异常System.out.println("异常.......");
//            String message = e.getMessage();
//            System.out.println(message);e.printStackTrace();}//多个异常捕获
//        catch(ArrayIndexOutOfBoundsException a) {//
//        }}//声明异常public static void add() throws Exception {//System.out.println("add......");int i = 1 / 0;}
}

finally块

在上述的try中,如果出现了异常,则异常后面的语句就不执行,但有些特定的语句是需要必须执行的。因此就需要finally块就是解决这个问题的,这是因为在Java中finally代码块中存放的代码都是一定会被执行的。

当在try语句块中打开了一些物理资源(磁盘文件/网络连接/数据库连接等),我们都得在使用完之后关闭打开的资源。

finally的语法:

 try{}catch(...){}finally{//无论try中是否发生异常,也无论catch是否捕获异常,也不管try和catch中是否有return语句,都一定会执行}或try{}finally{//无论try中是否发生异常,也不管try中是否有return语句,都一定会执行}

代码示例

package com.atguigu.demo;public class Demo6 {public static void main(String[] args) {try{System.out.println("程序开始执行了");int i = 1/0;}catch (Exception e){e.printStackTrace();}finally {System.out.println("这段代码总会执行");//这里没有写前面说的资源情况,主要为了方便理解}}
}

finally与return(面试)

形式一:从try回来

public class TestReturn {public static void main(String[] args) {int result = test("12");System.out.println(result);}public static int test(String str){try{Integer.parseInt(str);return 1;}catch(NumberFormatException e){return -1;}finally{System.out.println("test结束");}}
}

形式二:从catch回来

public class TestReturn {public static void main(String[] args) {int result = test("a");System.out.println(result);}public static int test(String str){try{Integer.parseInt(str);return 1;}catch(NumberFormatException e){return -1;}finally{System.out.println("test结束");}}
}

形式三:从finally回来

public class TestReturn {public static void main(String[] args) {int result = test("a");System.out.println(result);}public static int test(String str){try{Integer.parseInt(str);return 1;}catch(NumberFormatException e){return -1;}finally{System.out.println("test结束");return 0;}}
}

自定义异常

基本介绍

异常的情况有非常多,因此Java内部并不能把这些都包含进去,这就需要开发人员根据自己的实际业务情况进行自定义异常。比如年龄负数问题,考试成绩负数问题等等。

异常类如何定义:

  • 自定义一个编译期异常::自定义类 并继承于 java.lang.Exception。
  • 自定义一个运行时期的异常类:自定义类 并继承于 java.lang.RuntimeException。

代码示例

package com.atguigu.demo;public class Demo7 {public static void main(String[] args){try {new Input().method();}catch(WrongInputException wie) {System.out.println(wie.getMessage());}}
}
// 自定义的类继承Exception
class WrongInputException extends Exception {  WrongInputException(String s) {super(s);}
}
class Input {void method() throws WrongInputException {// 抛出自定义的类throw new WrongInputException("Wrong input");}
}

异常注意事项

多个异常使用捕获又该如何处理呢?

  1. 多个异常分别处理。
  2. 多个异常一次捕获,多次处理。(推荐)
  3. 多个异常一次捕获一次处理。

注意:多个异常一次捕获,多次处理的方式,要求多个catch中的异常不能相同,并且若catch中的多个异常之间有子父类异常的关系,那么子类异常要求在上面的catch处理,父类异常在下面的catch处理。

  • 运行时异常被抛出可以不处理。即不捕获也不声明抛出。

  • 如果finally有return语句,永远返回finally中的结果,避免该情况.

  • 如果父类抛出了多个异常,子类重写父类方法时,抛出和父类相同的异常或者是父类异常的子类或者不抛出异常。

  • 父类方法没有抛出异常,子类重写父类该方法时也不可抛出异常。此时子类产生该异常,只能捕获处理,不能声明抛出

深入浅出详细介绍Java异常,让你茅塞顿开般的感觉相关推荐

  1. [转]详细介绍java中的数据结构

    详细介绍java中的数据结构 本文介绍的是java中的数据结构,本文试图通过简单的描述,向读者阐述各个类的作用以及如何正确使用这些类.一起来看本文吧! 也许你已经熟练使用了java.util包里面的各 ...

  2. Java Scanner类的详细介绍(Java键盘输入)

    Java Scanner类的详细介绍(Java键盘输入) 一.Scanner类的简单使用 二.Scanner类的详细介绍 1.判断输入数据类型 2.next()与nextLine()的区别 3.求多个 ...

  3. java的移植性_详细介绍JAVA的可移植性

    软件可移植性指与软件从某一环境转移到另一环境下的难易程度.为获得较高的可移植性,在设计过程中常采用通用的程序设计语言和运行支撑环境.尽量不用与系统的底层相关性强的语言.下面介绍JAVA的可移植性. 1 ...

  4. 一篇不错的讲解Java异常的文章(转载)----感觉很不错,读了以后很有启发

    六种异常处理的陋习 你觉得自己是一个Java专家吗?是否肯定自己已经全面掌握了Java的异常处理机制?在下面这段代码中,你能够迅速找出异常处理的六个问题吗? 1 OutputStreamWriter ...

  5. 详细介绍Java垃圾回收机制

    垃圾收集GC(Garbage Collection)是Java语言的核心技术之一,之前我们曾专门探讨过Java 7新增的垃圾回收器G1的新特性,但在JVM的内部运行机制上看,Java的垃圾回收原理与机 ...

  6. java栈 类 堆_详细介绍Java中的堆和栈

    栈与堆都是Java用来在RAM中寄存数据的中央.与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆. Java的堆是一个运转时数据区,类的对象从中分配空间.这些对象经过new.newar ...

  7. 详细介绍Java和C++区别

    Java和C++都是面向对象语言.也就是说,它们都能够实现面向对象思想(封装,继承,多态).而由于C++为了照顾大量的C语言使用者,而兼容了C,使得自身仅仅成为了带类的C语言,多多少少影响了其面向对象 ...

  8. 简书 java jvm_详细介绍Java虚拟机(JVM)

    1. JVM生命周期 启动.启动一个Java程序时,一个JVM实例就产生了,任何一个拥有public static void main(String[] args)函数的class都可以作为JVM实例 ...

  9. it跟java的区别_详细介绍JAVA和C++区别

    JAVA和C++都是面向对象语言.也就是说,它们都能够实现面向对象思想(封装,继乘,多态).而由于c++为了照顾大量的C语言使用者,而兼容了C,使得自身仅仅成为了带类的C语言,多多少少影响了其面向对象 ...

最新文章

  1. eye care staff
  2. android设置输入框输入字符限制,Android里限制EditText控件可以输入字符内容的范围的方法...
  3. 多线程介绍和多线程模块-lock-互斥锁
  4. 【机器学习】opencv-视频中的人脸检测
  5. LeetCode 533. 孤独像素 II
  6. 图表如何又酷又实用?这个功能,能让大屏做出专家级效果
  7. markdown插入图片、音频视频
  8. 面试10大算法汇总+常见题目解答
  9. 计算机仿真课程建议,关于信息技术教学中的几点建议
  10. 2020 数学建模国赛 B 题参考思路
  11. uview ui与element ui的区别和用法
  12. 思科模拟器Cisco Packet Tracer菜单栏——参数选择
  13. AVI视频格式分析-封装格式
  14. 手机如何html5音频取,怎么用手机把视频里的音频提取?
  15. 详细分析PHP源代码后门事件及其供应链安全启示
  16. 日记500字初中计算机课,日记500字初中日常生活
  17. Android如何降低service被杀死概率
  18. 小米扫地机器人充电座指示灯不亮_扫地机器人常见问题及故障排除
  19. java存款只能存100_有100万存款,怎么样存银行才是最佳方法呢?
  20. GB/T 22239——2008信息系统安全等级保护基本要求审计相关

热门文章

  1. 【 MATLAB 】ellip 函数介绍(椭圆滤波器设计)
  2. Go借助PProf的一次性能优化
  3. redis 系列25 哨兵Sentinel (高可用演示 下)
  4. MapReduce过程详细分析
  5. [转载]PhotoShop性能优化
  6. 这就是那个feature map256 256向量
  7. 一个简单好用的Android Tab 设计与实现
  8. 【转】web 前端研发工程师编程能力飞升之路
  9. 一起学DNS系列(一)基础、概览
  10. PetShop 4.0讨论专贴(QA)