异常:
1.概述:
程序出现的不正常的情况。
2.异常的体系:
Throwable
|-- Error 这种问题是一个严重问题,一般出现这种问题,需要一起解决(程序员只能避免严重问题),比如:内存溢出(OutOfMemory);|-- Exception
|-- RuntimeException 运行期异常,我们需要修正代码|-- 非RuntimeException 编译期异常,必须处理的,否则程序编译不通过
3.异常的描述:
哪一个包下的异常,并且将报错信息打印在控制台。
4.异常的处理:
a.JVM的默认处理
把异常的名称,原因,位置等信息输出在控制台。
b.自己处理
i.捕获异常 try...catch..finallyii.抛出异常 thorws
捕获异常:
1.格式:
try{
可能出现问题的代码;
}catch(异常类名 变量名){
输出语句;
}finally{
释放资源;
}
如果try里面的代码出现问题了,jvm会生成异常对象,然后抛出来和catch中描述的这个异常信息进行匹配,判断如果一致,这里会输出处理语句(输出语句)//可能出现问题的代码如果和catch里面的异常类名能匹配,则打印输出语句。
2.变形方式:
try{
可能出现问题的代码
}catch(异常类名 变量名){
提示信息
}
try...catch...try...catch...catchtry...catch...catch...finally(开发常用)
3.两个异常的处理:
a.一个一个去try...catchb.一个try,多个catch注意:
a.在实际开发中,捕获异常的时候,最好给出具体的异常类,不要随意使用Exceptionb.捕获异常:使用一个try多个catch的情况,catch中异常类名是一种平级关系,如果出现父子关系,那么这种将最大的异常写在最后。
4.JDK7以后出现的新的捕获异常的方式
try{
可能出现问题的代码
}catch(异常类名1 变量名1){
提示
}catch(异常类名2 变量名2){
......
}
新的方式:try{
可能出现问题的代码
}catch(异常类名1 | 异常类名2 | 异常类名3 变量名){
......
}注意:
有一个弊端,不够好,在开发中,可能出现同类型问题,需要捕获同一个异常信息。
5.java程序中编译时期异常和运行时期异常的区别:
a.编译时期异常:需要我们去处理,否则编译不通过,显示处理b.运行时期异常:无序显示处理,也可以像编译时期异常处理一样
6.异常类中的一些方法:
public String getMessage():返回的是一个异常的消息字符串piblic String toString():返回的是一个简单的描述信息当前类对象 name:全路径名":"(冒号:空格) + getMessage()public void printStackTrace():描述异常信息,以及出现的具体位置在哪里,返回的是void类型,直接在控制台的!
public class Demo1 { public static void main(String[] args) { Method1(); Method2(); } private static void Method2() { int []a={1,2,3}; try { System.out.println(a[3]); } catch (ArrayIndexOutOfBoundsException e) { System.out.println("数组越界了"); } } private static void Method1() { int a = 10; int b = 0; try { System.out.println(a/b); } catch (ArithmeticException e) { System.out.println("分母不能为0"); } } }
public class Demo2 { public static void main(String[] args) { int a = 10 ; int b = 0; int []c={1,2,3}; try { System.out.println(a/b); System.out.println(c[3]); } catch (ArithmeticException e ){ System.out.println("分母不能为0"); } catch (ArrayIndexOutOfBoundsException e) { System.out.println("数组越界了"); } } }
抛出异常(thorws):
1.为什么要使用抛出异常:
当我们处理异常,如果没有一些权限处理异常,那我们就不处理了,通过开发工具,提示抛出异常。
2.throws和throw的区别?
a.thorws:
一般是在方法声明上抛出。抛出的是一个异常类名,可以抛出多个异常,中间用逗号隔开。throws表示抛出异常,这段代码可能会抛出异常( 指的是抛出异常的可能性).一般情况,throws用的比较多
b.thorw:
一般在方法中进行抛出抛出的是一个异常类对象(匿名对象的方式)throw表示抛出,肯定的抛出异常(具体异常),走到这块代码,一定会执行throw中的异常 在语句中进行处理
import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; public class Demo02 { public static void main(String[] args) throws ParseException { //定义字符串变量 String s = "2017-8-8"; //创建对象 SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date d = sd.parse(s);//编译时期异常需要抛出异常 System.out.println(d); } } /* out: Exception in thread "main" java.text.ParseException: Unparseable date: "2017-8-8" at java.text.DateFormat.parse(DateFormat.java:366) at Exception.Demo02.main(Demo02.java:13) */
public class Demo01 { public static void main(String[] args) throws Exception { fun1(); fun2(); } private static void fun1() throws Exception{ //定义两个变量 int a = 1; int b = 0; if(b==0){ throw new ArithmeticException();//代码走到这块:表示一定会执行这个异常 }else{ System.out.println(a/b); } } private static void fun2() throws Exception { //可能会抛出异常 //定义两个变量 int a = 1; int b = 0; if(b==0){ throw new Exception();//直接指定的异常:大方向的异常 }else{ System.out.println(a/b); } } }
finally关键字和异常类相关问题
1.概述:
finally用于释放资源,它的代码永远会执行。特殊情况:在执行到finally之前jvm退出了注意:finally中的代码是一定会执行的,一般用在IO流中和数据库中;
2.执行代码的顺序:
try{
可能出现问题的代码;
}catch(异常类名 变量名){
输出语句;
}finally{
释放资源;
}
import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; public class finallyDemo { public static void main(String[] args) { //定义字符串 String s = "2017-8-9"; //创建对象 SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // 定义一个变量 Date d = null; try { d=sd.parse(s); } catch (ParseException e) { e.printStackTrace(); // System.exit(0);//jvm退出 } finally{ System.out.println("这里必须执行,用来释放资源"); } System.out.println("d:"+d); } } /* out: java.text.ParseException: Unparseable date: "2017-8-9" at java.text.DateFormat.parse(DateFormat.java:366) at Exception.finallyDemo.main(finallyDemo.java:27) 这里必须执行,用来释放资源 d:null
3.final、finalize、finally三者之间的区别?(★★★★★)
a.final:最终的,终态的
final修饰类,该类不能被继承final修饰成员变量,该变量是自定义常量final修饰成员方法,该方法不能被重写
b.finalize
和垃圾回收期有关系:运行垃圾回收器的方法:gc().调用gc(),实质是调用了通过重写了Object中的finalize方法
c.finally
出现在IO流中或者数据中,用来释放资源的!
4.(面试题)如果catch有return语句,finally中的会执行吗?如果会,是在return前执行还是在return后执行?
会执行finally中的代码,是在return前执行确切的说实在代码中间执行!
public class finallyDemo2_return { public static void main(String[] args) { System.out.println(fun());//30 } public static int fun() { int a = 10 ; try{ a = 20; System.out.println(a/0); }catch(Exception e){ a = 30; return a; /* * 此时 * a = 30;return 30 * 但是有finally 所以会执行finally里的代码 */ }finally{ a = 40; // return a; } return a; } }
5.异常类的注意事项:
a.父的方法有异常抛出,子的重写方法在抛出异常的时候必须要小于(异常类的子类)等于父的异常b.父的方法没有异常抛出,子的重写方法不能有异常抛出只能 try...catch(这种情况只能子类中进行捕获异常);c.父的方法抛出多个异常,子的重写方法必须比父少或者小
6.自定义异常:
有时候在实际开发中,可能会需要自己定义一个异常类;不是说起以类名就是可以当作异常类,必须自定义的类继承Exception或者RuntimeException,那么这样的类,才是自己定义的异常类
public class MyException extends Exception {
//添加空参数构造
public MyException(){}
public MyException(String m){
super(m);
}
}
import java.util.Scanner;
public class StudentDemo {
public static void main(String[] args) {
//创建键盘录入对象
Scanner sc = new Scanner(System.in) ;
//录入并接收数据
System.out.println("请输入您的成绩:");
int score = sc.nextInt() ;
//创建老师对象
Teacher t = new Teacher() ;
try {
t.check(score);
} catch (MyException e) {
e.printStackTrace();
}
}
}
public class Teacher {
//检查分数的方法
public static void check(int score) throws MyException{
//成绩大于100或者成绩小于0
if(score>100 || score<0){
System.out.println("成绩必须在0~100之间");
}else{
System.out.println("符合我们的成绩规则...");
}
}
}