Throwable
1、Error
- Error java虚拟机无法解决的严重问题。如jvm系统内部错误、资源耗尽等情况。(一般不不编写针对性的代码进行处理)
package Error;
public class Error_ {
public static void main(String[] args) {
/*
* 1.栈溢出
* Exception in thread "main" java.lang.StackOverflowError
*
* */
//main(args);
/*
* 2.堆溢出
* Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
* */
//Integer[] arr = new Integer[1024*1024*1024];
}
}
2、Excption
- 其他因编程错误或偶然的外在因素导致的一般性问题。可以使用针对性代码进行处理。
空指针访问
试图访问不存在的文件
网络连接中断
数组角标越界
3、异常类型
- 运行时异常
- 空指针异常
package Error;
public class Error_ {
public static void main(String[] args) {
/*
* 1、空指针异常
* Exception in thread "main" java.lang.NullPointerException
* */
int[] a = null;
a.toString();
}
}
- 数组下标越界
package Error;
public class Error_ {
public static void main(String[] args) {
/*
* 2、数组角标越界
* Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3
* */
int[] a = new int[3];
System.out.println(a[3]);
}
}
- 字符串访问越界
/*
1. 3、字符串访问越界
2. Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 3
3. */
String s = "123";
System.out.println(s.charAt(3));
- 类型转换异常
比如:向下转型(父类转换成子类-是不安全的,因为父类可能有很多子类,因此不知道转换成哪个子类)
/*
1. 4、类型转换异常
2. Exception in thread "main" java.lang.ClassCastException: java.util.Date cannot be cast to java.lang.String
3. */
Object o = new Date();
String s = (String)o;
- 算术运算异常
/*
* 5、算术运算异常
* Exception in thread "main" java.lang.ArithmeticException: / by zero
* */
int a= 1;
int b = 0;
System.out.println(a/b);
- 数据类型转换异常
/*
1. 6、数据类型转换异常
2. Exception in thread "main" java.lang.NumberFormatException: For input string: "123a"
3. */
String a = "123a";
int i = Integer.parseInt(a);
- 输入类型不匹配异常
/*
* 7、输入类型不匹配异常
* 输入:aaa
* Exception in thread "main" java.util.InputMismatchException
* */
Scanner input = new Scanner(System.in);
int i = input.nextInt();
System.out.println(i);
- 编译时异常
在编译时发生的异常(也就是在编写代码的时候,没有语法错误时,代码也报红色的代码,这些代码就出现了编译时异常。比如使用io流时不处理异常)
4、处理异常
4.1、try-catch
package Error;
/*
* 异常处理,抓抛模型
* 过程一:“抛”,程序正常执行的过程中,一旦出现异常,就会在异常代码处生成一个对应的异常类的对象。
* 并将此对象抛出。
* 一旦抛出对象以后,其后的代码就不再执行。
*
* 过程二:“抓”,可以理解为异常的处理方式,1、try-catch-finally 2、throws
*
*
* try{
* //可能出现异常的代码
* }catch(异常类型1 变量名1){
* //处理异常的方式
* }catch(异常类型2 变量名2){
* //处理异常的方式
* }finally{
* //一定会执行的代码
* }
*
* 说明:
* 1. finally是可选的
* 2. 使用try将可能出现异常的代码包装起来,在执行过程中,一旦出现异常,就会生成一个对应异常的对象,根据此对象的类型
* 就能去catch中进行匹配
* 3. catch中的异常类型如果没有子父关系,当异常类型匹配时,谁声明在上面就执行谁(多个catch只执行其中一个)
* * */
public class try_catch {
public static void main(String[] args) {
String a = "123a";
try {
int i = Integer.parseInt(a);
System.out.println("11111");
}catch (NumberFormatException e){
System.out.println("数据转换异常"+e.getMessage()); //异常信息提示
e.printStackTrace(); //输出原来的异常信息
// return;
}finally {
System.out.println("最后");
}
System.out.println("6666");
}
}
- 使用try-catch可以解决编译时异常,但是可能还会出现运行时异常
/*
* 1、编译时异常
* 使用try-catch解决编译时异常
* */
try{
File file = new File("123.text");
FileInputStream fileInputStream = new FileInputStream(file);
int data = fileInputStream.read();
while (data !=-1){
System.out.println((char) data);
data = fileInputStream.read();
}
fileInputStream.close();
}catch (IOException e){
System.out.println(e.getMessage());
}
- 在开发中运行时异常一般不会使用try-catch处理,因为运行时异常是需要用代码去解决的。(比如空指针异常)
- 编译时异常是肯定需要try-catch处理的。
4.2、throws + 异常类型
package Error;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class Throws_ {
public static void main(String[] args) {
try {
Throws_.IOTest();
} catch (IOException e) {
e.printStackTrace();
}finally {
System.out.println("1111");
}
}
/*
* 异常处理的方式:throws + 异常类型
* 1、这种方式也算解决了异常,(它以抛出异常的方式解决异常)但是它解决的是这个方法的异常。当其他对象调用时需要解决这个异常
* 2、其实真正处理异常的是try-catch
*
* */
public static void IOTest() throws IOException{
File file = new File("123.text");
FileInputStream fileInputStream = new FileInputStream(file);
int data = fileInputStream.read();
while (data !=-1){
System.out.println((char) data);
data = fileInputStream.read();
}
fileInputStream.close();
}
}
- 当一个类已经抛出了(throws + 异常类型),它的子类抛出的异常类型不能比父类的异常类型大
- 也就是通过继承后,子类抛出的异常类型必须比父类的小(精确)
4.3、如何选择处理异常的方式(try-catch和 throws)
5、手动抛出异常——throw
package Error;
public class throw_ {
/*
* 手动抛出异常
* */
public static void testThrow(int j){
int i = 10;
if (j>0){
System.out.println(i/j);
}else {
throw new RuntimeException("分母不能为零!");
}
}
public static void main(String[] args) {
throw_.testThrow(10);
}
}
6、throws和throw的区别
7、自定义异常类
package Throwable;
/*
* 自定义异常类-运行时的异常类
* */
public class MyException extends RuntimeException {
static final long serialVersionUID = -888717899101111L;
/*
* 如何自定义异常类
* 1、继承现有的异常结构,比如RuntimeException、Exception等
* 2、提供全局变量:serialVersionUID
* 3、提供重载的构造器
* */
public MyException(){
}
public MyException(String msg){
super(msg);
}
}
class TestMyException{
/*
* 手动抛出异常
* */
public static void testThrow(int j){
int i = 10;
if (j>0){
System.out.println(i/j);
}else {
throw new MyException("分母不能为零!");
}
}
public static void main(String[] args) {
throw_.testThrow(0);
}
}
8、常见面试题
- throw与throws
1、throw声明在方法体里,throws声明在方法的声明处
2、throw用来创建异常对象(手动抛出一个异常对象),throws是处理异常的一种方式(抛出异常也是处理异常的方式)
3、java异常是使用抓抛模型的,throw在抛中起作用,throws在抓中起作用