JAVA基础 异常
异常Exception 和 错误Error 都是Throwable的子类,因为Error一般是JVM生成并抛出的,不由我们程序员所控制,因此我们现在只说下我们可以控制的异常Exception。
Exception 一般分为 编译时异常和运行时异常。
编译时异常|检查时异常 CheckedException
是在编译期间出现的异常,急需要我们必须去处理的,否则无法运行。
CheckedException是除了RuntimeException外的所有继承自Exception的子类。
常见的编译时异常 文件未找到异常
//编译时异常 文件未找到异常 FileNotFoundException
//IO流 常见;之后会详细说的。
InputStream a = new FileInputStream("D:/test.txt");
编译时异常是在编译的时候就出现,要么自己解决(try catch),要么就向上抛出(throws)。
异常的处理方法
throws 异常抛出
在方法的内部出现异常,可以抛出到方法上面,**谁调用方法谁处理,**最终肯定需要处理。未来统一抛出统一处理。
//throws FileNotFoundException 当路径没有找到文件时,抛出文件未找到异常
static void test() throws FileNotFoundException {
//这个是IO流中常见的,之后会详细说的。
InputStream is = new FileInputStream("D:/test.txt");
}
因为上面的文件未找到异常在调用FileInputStream这个方法的时候比较常见,就设置成当没有找到文件时,需要怎么做,可以是向上继续抛出异常,也可以是下面的捕获异常。这是编译时异常,必须要用这两种的一种,否则编译报错。
try…catch 异常捕获
语法:
try{
可能会出现异常的代码;
}catch(FileNotFoundException e){
出现异常执行的代码;
}catch(异常类型 变量名){
出现异常执行的代码;
}…
finally{
无论try中的代码是否出现异常,都会执行的代码;
}
try{
System.out.println(5/0);
}
}catch(FileNotFoundException e){
e.printStackTrace();
System.out.println("出现文件未找到异常了");
}catch(ArithmeticException e){
e.printStackTrace();
System.out.println("出现数学异常了");
}catch(Exception e){ //类型大的异常放到后面
e.printStackTrace();
System.out.println("出现异常了");
}finally {
//无论是否遇到return,都会执行finally中的代码
System.out.println("我是finally.....");
}
System.out.println(i);
}
注意:一个try后面是可以跟多个catch的,catch是从上至下依次来进行判断的
try中如果没有出现异常,不执行catch判断捕获
try中一旦出现异常,try中后面的代码不会执行
如果catch中捕获的异常类型比较大,应该写在最后(例如上面的Exception)
finally当前try …catch结构执行完毕会执行finally中的代码,可以理解为是关闭并且之后释放try catch的内存。
运行时异常 RuntimeException
是发生在程序的运行期间,可以通过增强程序的健壮性处理,比如用if等。
常见的异常种类和处理方式:
NullPointException 空指针
public static void main(String[] args) {
//异常
//数组为null 查询数组下标为0的值,会出现空指针异常
int[] arr = null;
//NullPointException 空指针
//解决
/*if(arr!=null){
System.out.println(arr[0]);
}*/
//空指针异常 会出现异常
System.out.println(arr[0]);
}
ArrayIndexOutOfBoundsException数组索引越界异常
public static void main(String[] args) {
//异常
int[] arr = new int[]{1,2,3,4,5};
int index = -1;
//解决
/*if (index >=0 && index<=arr.length-1) {
System.out.println(arr[index]);
}*/
//数组索引越界异常 会出现异常
System.out.println(arr[index]);
}
NegativeArraySizeException 数组长度负数异常
//NegativeArraySizeException 数组长度负数异常(长度为0或者负数都是会抛出的)
public static void main(String[] args) {
int size = 0;
//解决
/*if(size>0){
arr = new int[size];
}*/
//数组长度负数异常,出现异常
arr = new int[size];
}
ClassCastException 类型转换异常
//ClassCastException 类型转换异常
public static void main(String[] args) {
Object obj = ""; //多态 向上转型
//解决,用instanceof 判断obj是否是System(或其父类)的实例
/*if(obj instanceof System){
System str = (System)obj;
}*/
//类型转换异常
System str = (System)obj;
}
ArithmeticException 数学异常
//ArithmeticException 数学异常
public static void main(String[] args) {
int a =5;
int b =0;
/*if(b!=0){
System.out.println(a/b);
}*/
//数学异常
System.out.println(a/b);
}
.NumberFormatException 数字格式异常
//NumberFormatException 数字格式异常
String s = "123abc";
//处理方法,这里遍历s的字符数组,如果有不在0~9的就return,不执行格式转化
/*for(char ch:s.toCharArray()){
if(ch>='0'&&ch<='9'){
continue; //没有continue也可以
}else{
return;
}
}
System.out.println(Integer.valueOf(s));*/
//将s转化为数字格式(整型)
System.out.println(Integer.valueOf(s));
上面的几种是通过if等判断增强程序的健壮性来解决异常的,方法也不知上面的例子。同样,上面的运行异常也可以用throws和try…catch处理。但是,如果是编译时异常,就只能用throws和try…catch来处理了。
自定义异常
throw 制造异常
一个异常类型的对象如果不通过throw关键字,就是一个普通的对象没有异常的作用和特点,当使用throw关键字制造异常,java才会把这个对象识别成异常
直接或者间接的继承自Exception
运行时异常必须 直接或者间接的继承自RuntimeException
//自定义年龄异常
class AgeExpception extends RuntimeException{
public AgeExpception(){}
public AgeExpception(String message){
super(message);
}
}
//创建用户类,按JavaBean创建
class User{
private String name;
private int age;
public User() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
//当年龄不合法的时候,抛出异常
public void setAge(int age){
if(age<18 || age>100){
throw new AgeExpception(age+"不合法!!!");
}
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}