(1)编译错误:是因为程序没有遵循语法规则,编译程序能够自己发现并且提示我们错误的原因和位置。
(2)运行时错误:是因为程序在执行时,运行环境发现了不能执行的操作。
(3)逻辑错误:是因为程序没有按照预期的逻辑顺序执行
异常也就是指程序运行时发生错误,而异常处理就是对这些错误进行处理和控制。
序号 | 异常名称 | 异常描述 |
---|---|---|
1 | java.lang.NullPointerException | 空指针异常:对象为空,并且调用相应方法。 |
2 | java.lang.ClassNotFoundException | 找不到指定类 |
3 | java.lang.ArrayIndexOutOfBoundsException | 数组下标越界 |
4 | java.lang.NumberFormatException: | 数字格式化异常 |
5 | java.lang.ArithmeticException: | 数学运算异常 |
6 | java.lang.StackOverflowError | 内存空间溢出错误,方法递归调用中,经常发生 |
7 | java.lang.ClassCastException | 类型转换异常,向下转型中经常发生 |
8 | java.text.ParseException | 时间格式化异常,SimpleDateFormart中经常发生 |
9 | java.util.InputMismatchException | 输入类型不匹配异常 |
1.try-catch
try:尝试着执行可能会出现异常的代码
catch:如果try中的代码在执行过程中,出现了异常,捕获该异常,如果没有异常,就不执行。
//单个try-catch
try{
}catch(){
}
//多个catch
try{
}catch(){
}catch(){
}
//多个catch在捕获异常时,子类异常catch块要放在前面,父类异常catch块放在后面
try{
}catch(){
}finally{
//通常用来释放资源
}
@Test//空指针异常--引用为空,还去调用方法。
public void test(){
Book [] books = new Book[5];
//System.out.println("books[0].getName()="+books[0].getName());
String s = null;
System.out.println(s);
System.out.println(s.length());
}
@Test//数组下标越界异常
public void test1(){
Book [] books = new Book[5];
books[5]=new Book();
}
public static void main(String[] args) {
//捕获异常 != 解决异常
for (int i = 1; i <= 5; i++) {
Scanner sc = new Scanner(System.in);
try {
System.out.printf("请录入第 %d 名同学的成绩:",i);
int score = sc.nextInt();
System.out.println("");
//break;
//return;
//System.exit(1);//强制性关闭虚拟机
}catch (InputMismatchException e){
System.out.println("出现了输入类型不匹配的异常--精准捕获");
//break;
//return;
System.exit(1);
}catch (NullPointerException e){
System.out.println("出现了空指针异常");
}catch (RuntimeException e){
System.out.println("运行时异常,是上面两个异常的父类---放大捕获");
}catch (Exception e){
System.out.println("运行时异常,是上面两个异常的父类---在放大捕获");
}catch (Throwable e){
System.out.println("运行时异常,是上面两个异常的父类---再再放大捕获");
}finally {
System.out.println("最终代码块--不管是否有异常,都会执行,break,return不具备躲避finally功能");
}
}
}
Java的异常机制:
1.建立大量的用于表述某种异常的类,组成一个以Throwable为首的异常家族。
2.当程序执行出现异常时,立即创建相应异常类的对象。
3.使用catch(异常类 e)捕获创建的异常对象。
1.使用throws声明异常
运用于方法声明之上,用于表示当前方法不处理异常,而是提箱该方法的调用者类处理异常
public void fun1() throws ParseException {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = format.parse("2020-10-12");
}
2.使用throw抛出异常
throw用在方法内,用来抛出一个异常对象,将这个异常对象传递到调用者处,并结束当前方法的执行。
public void fun2() {
throw new NullPointerException("空指针异常");
System.out.println("hello world");//会报红,提示unreachable statement,该语句不可能被执行
}
@Test//嵌套try-catch
public void fun2() {
try {
throw new Exception("非运行时异常,哈哈哈");
} catch (Exception e) {
e.printStackTrace();
try {
throw new ParseException("解析异常,哈哈哈",0);
} catch (Exception ex) {
ex.printStackTrace();
}
}finally {
try {
throw new TimeoutException("超时异常,哈哈哈");
} catch (TimeoutException e) {
e.printStackTrace();
try {
throw new SQLException("SQL异常");
} catch (SQLException ex) {
ex.printStackTrace();
}
}
}
}
//代替返回语句
public int funR1(){
try {
return 1;
}catch (Exception e){
throw new RuntimeException();
}
}
public int funR2(){
if(true) {
return 1;
}else{
throw new RuntimeException();
}
}
JDK中定义了大量的异常类,可以描述编程时出现的大部分异常情况,但对于一些特殊情景下的异常,我们可以自己去定义。
创建步骤:
创建一个异常类
加入异常家族中(继承某个异常父类)
public class HeroNotExistException extends RuntimeException {
private String m;
public String getM() {
return m;
}
public void setM(String m) {
this.m = m;
}
//两个参数的有参构造,一个传递给父类Throwable,一个自己用
public HeroNotExistException(String message, String m){
super(message);
this.m=m;
}
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
System.out.println("请输入您最欣赏的历史人物:");
String name = sc.next();
if(name.equals("孙悟空")){
try{
throw new HeroNotExistException("英雄人物不存在","哈哈");
}catch (HeroNotExistException e){
e.printStackTrace();
System.out.println(e.getM());
}
}
}
}
总结
1、java中异常分为两大类:
checked exception (非运行时异常)
unchecked exception (运行时异常)
2、java中所有的异常类都会直接或间接地继承自Exception。
3、RuntimeException类也是直接继承Exception类,它叫运行时异常,换句话说:java中所有的运行时异常都会直接或间接继承自RuntimeException。
4、java中凡是继承自Exception而不是继承自RuntimeException的类都是非运行时异常。对于非运行时异常,必须要对其进行处理,处理方式有两种:
使用try…catch捕获处理
在所在方法声明 throws Exception
5、对于运行时异常,我们可以不对其处理,推荐不对其处理
6、空指针异常,出现该异常时原因市在于某个引用为null,但是还使用它调用方法。
7、自定义异常,通常就是定义了一个继承自Exception类的子类,那么这个类就是一个自定义异常类。通常情况下,我们都会直接继承自Exception,一般不会继承某个运行时异常类。
8、我们可以使用多个catch块来捕获异常,这时需要将父类型catch块放到子类型catch之后,这样才能保证后续的catch可能被执行,否则子类型的catch将永远无法到达,java编译器会编译报错。
11、如果try块中存在return语句,那么首先也需要将finally块中的代码执行完毕,然后方法再返回。
12、如果try块中存在System.exit(0),会终止当前运行的java虚拟机,程序会强制性结束执行。