本文已参加[新人创造礼]活动,一同开启创造之路。
哈喽,咱们好!我是Why,一名在读学生,目前刚刚开端进入自己的编程学习生涯。虽然学习起步较晚,但我坚信做了才有0或1的或许。学了javaee一段时间今后也是选择在上分享自己的日常笔记,也希望能够在很多道友的咱们庭中浑然一体。 本文首要讲解java反常,假如咱们读后觉得有用的话,还请咱们多多支持博主:欢迎 ❤️点赞、收藏⭐、留言 ✨✨✨个人主页:JinHuan
反常
1、什么是反常,java供给反常处理机制有什么用? 以下程序履行进程中发生了不正常的状况,而这种不正常的状况叫做:反常 java言语是很完善的言语,供给了反常的处理办法,以下程序履行进程中呈现了不正常状况, java把该反常信息打印输出到控制台,供程序员参阅。程序员看到反常信息之后,能够对 程序进行修改,让程序愈加的强健。 什么是反常:程序履行进程中的不正常状况。 反常的效果:增强程序的强健性。 2、以下程序履行控制台呈现了: Exception in thread "main" java.lang.ArithmeticException: / by zero at com.bjpowernode.javase.exception.ExceptionTest01.main(ExceptionTest01.java:14) 这个信息被咱们称为:反常信息。这个信息是JVM打印的。
栗子
public class ExceptionTest01 { public static void main(String[] args) { int a = 10; int b = 0; // 实践上JVM在履行到此处的时分,会new反常目标:new ArithmeticException("/ by zero"); // 并且JVM将new的反常目标抛出,打印输出信息到控制台了。 int c = a / b; System.out.println(a + "/" + b + "=" + c); // 此处运行也会创立一个:ArithmeticException类型的反常目标。 //System.out.println(100 / 0); // 我观察到反常信息之后,对程序进行修改,愈加强健。 /* int a = 10; int b = 2; if(b == 0) { System.out.println("除数不能为0"); return; } // 程序履行到此处表示除数必定不是0 int c = a / b; System.out.println(a + "/" + b + "=" + c); */ } }
反常的存在办法
1、反常在java中以类的办法存在,每一个反常类都能够创立反常目标。 2、反常对应的现实生活中是怎样的? 火灾(反常类): 2008年8月8日,小明家着火了(反常目标) 2008年8月9日,小刚家着火了(反常目标) 2008年9月8日,小红家着火了(反常目标) 类是:模板。 目标是:实践存在的个别。 钱包丢了(反常类): 2008年1月8日,小明的钱包丢了(反常目标) 2008年1月9日,小芳的钱包丢了(反常目标)
栗子
public class ExceptionTest02 { public static void main(String[] args) { // 经过“反常类”实例化“反常目标” NumberFormatException nfe = new NumberFormatException("数字格式化反常!"); // java.lang.NumberFormatException: 数字格式化反常! System.out.println(nfe); // 经过“反常类”创立“反常目标” NullPointerException npe = new NullPointerException("空指针反常发生了!"); //java.lang.NullPointerException: 空指针反常发生了! System.out.println(npe); } }
运行时反常实例
public class ExceptionTest03 { public static void main(String[] args) { /* 程序履行到此处发生了ArithmeticException反常, 底层new了一个ArithmeticException反常目标, 然后抛出了,由于是main办法调用了100 / 0, 所以这个反常ArithmeticException抛给了main办法, main办法没有处理,将这个反常主动抛给了JVM。 JVM终究终止程序的履行。 ArithmeticException 承继 RuntimeException,归于运行时反常。 在编写程序阶段不需求对这种反常进行预先的处理。 */ System.out.println(100 / 0); // 这儿的HelloWorld没有输出,没有履行。 System.out.println("Hello World!"); } }
编译时反常的实例
/* 以下代码报错的原因是什么? 由于doSome()办法声明方位上运用了:throws ClassNotFoundException 而ClassNotFoundException是编译时反常。有必要编写代码时处理,没有处理 编译器报错。 */ public class ExceptionTest04 { public static void main(String[] args) { // main办法中调用doSome()办法 // 由于doSome()办法声明方位上有:throws ClassNotFoundException // 咱们在调用doSome()办法的时分有必要对这种反常进行预先的处理。 // 假如不处理,编译器就报错。 //编译器报错信息: Unhandled exception: java.lang.ClassNotFoundException //doSome(); } /** * doSome办法在办法声明的方位上运用了:throws ClassNotFoundException * 这个代码表示doSome()办法在履行进程中,有或许会呈现ClassNotFoundException反常。 * 叫做类没找到反常。这个反常直接父类是:Exception,所以ClassNotFoundException归于编译时反常。 * @throws ClassNotFoundException */ public static void doSome() throws ClassNotFoundException{ System.out.println("doSome!!!!"); } }
反常的处理办法
import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; /* 处理反常的榜首种办法: 在办法声明的方位上运用throws关键字抛出,谁调用我这个办法,我就抛给谁。抛给调用者来处理。 这种处理反常的态度:上报。 处理反常的第二种办法: 运用try..catch句子对反常进行捕捉。 这个反常不会上报,自己把这个事儿处理了。 反常抛到此处为止,不再上抛了。 留意: 只需反常没有捕捉,选用上报的办法,此办法的后续代码不会履行。 其他需求留意,try句子块中的某一行呈现反常,该行后边的代码不会履行。 try..catch捕捉反常之后,后续代码能够履行。 */ "在今后的开发中,处理编译时反常,应该上报仍是捕捉呢,怎样选? 假如希望调用者来处理,选择throws上报。 其它状况运用捕捉的办法。 public class ExceptionTest06 { " 一般不主张在main办法上运用throws,由于这个反常假如真实的发生了,必定会抛给JVM。JVM只有终止。 // 反常处理机制的效果便是增强程序的强健性。怎样能做到,反常发生了也不影响程序的履行。所以 // 一般main办法中的反常主张运用try..catch进行捕捉。main就不要持续上抛了。 /* public static void main(String[] args) throws FileNotFoundException { System.out.println("main begin"); m1(); System.out.println("main over"); } */ public static void main(String[] args) { // 100 / 0这是算术反常,这个反常是运行时反常,你在编译阶段,能够处理,也能够不处理。编译器不论。 //System.out.println(100 / 0); // 不处理编译器也不论 // 你处理也能够。 /* try { System.out.println(100 / 0); } catch(ArithmeticException e){ System.out.println("算术反常了!!!!"); } */ System.out.println("main begin"); try { // try测验 m1(); // 以上代码呈现反常,直接进入catch句子块中履行。 System.out.println("hello world!"); } catch (FileNotFoundException e){ // catch后边的如同一个办法的形参。 // 这个分支中能够运用e引证,e引证保存的内存地址是那个new出来反常目标的内存地址。 // catch是捕捉反常之后走的分支。 // 在catch分支中干什么?处理反常。 System.out.println("文件不存在,或许路径过错,也或许该文件被删去了!"); System.out.println(e); //java.io.FileNotFoundException: D:course1-课学习办法.txt (体系找不到指定的路径。) } // try..catch把反常捉住之后,这儿的代码会持续履行。 System.out.println("main over"); } private static void m1() throws FileNotFoundException { System.out.println("m1 begin"); m2(); // 以上代码出反常,这儿是无法履行的。 System.out.println("m1 over"); } // 抛其他不行,抛ClassCastException阐明你仍是没有对FileNotFoundException进行处理 //private static void m2() throws ClassCastException{ // 抛FileNotFoundException的父目标IOException,这样是能够的。由于IOException包含FileNotFoundException //private static void m2() throws IOException { // 这样也能够,由于Exception包含所有的反常。 //private static void m2() throws Exception{ // throws后边也能够写多个反常,能够运用逗号离隔。 //private static void m2() throws ClassCastException, FileNotFoundException{ private static void m2() throws FileNotFoundException { System.out.println("m2 begin"); // 编译器报错原因是:m3()办法声明方位上有:throws FileNotFoundException // 咱们在这儿调用m3()没有对反常进行预处理,所以编译报错。 // m3(); m3(); // 以上假如呈现反常,这儿是无法履行的! System.out.println("m2 over"); } private static void m3() throws FileNotFoundException { // 调用SUN jdk中某个类的结构办法。 // 这个类还没有接触过,后期IO流的时分就知道了。 // 咱们仅仅凭借这个类学习一下反常处理机制。 // 创立一个输入流目标,该流指向一个文件。 /* 编译报错的原因是什么? 榜首:这儿调用了一个结构办法:FileInputStream(String name) 第二:这个结构办法的声明方位上有:throws FileNotFoundException 第三:经过类的承继结构看到:FileNotFoundException父类是IOException,IOException的父类是Exception, 终究得知,FileNotFoundException是编译时反常。 过错原因?编译时反常要求程序员编写程序阶段有必要对它进行处理,不处理编译器就报错。 */ //new FileInputStream("D:course1-开课学习办法.txt"); // 咱们选用榜首种处理办法:在办法声明的方位上运用throws持续上抛。 // 一个办法体傍边的代码呈现反常之后,假如上报的话,此办法完毕。 new FileInputStream("D:course1-课学习办法.txt"); System.out.println("假如以上代码出反常,这儿会履行吗??????????????????不会!!!"); } }
public class ExceptionTest05 { // 榜首种处理办法:在办法声明的方位上持续运用:throws,来完结反常的持续上抛。抛给调用者。 // 上抛类似于推卸责任。(持续把反常传递给调用者。) /* public static void main(String[] args) throws ClassNotFoundException { doSome(); } */ // 第二种处理办法:try..catch进行捕捉。 // 捕捉等于把反常拦下了,反常真实的处理了。(调用者是不知道的。) public static void main(String[] args) { try { doSome(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } public static void doSome() throws ClassNotFoundException{ System.out.println("doSome!!!!"); } }
About Try-catch
import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; 深入try..catch "1、catch后边的小括号中的类型能够是具体的反常类型,也能够是该反常类型的父类型。 "2、catch能够写多个。主张catch的时分,精确的一个一个处理。这样有利于程序的调试。 "3、catch写多个的时分,从上到下,有必要恪守从小到大。 public class ExceptionTest07 { /* public static void main(String[] args) throws Exception, FileNotFoundException, NullPointerException { } */ /*public static void main(String[] args) throws Exception { }*/ public static void main(String[] args) { //编译报错 /*try { FileInputStream fis = new FileInputStream("D:course2-JavaSEdocumentJavaSE进阶讲义JavaSE进阶-01-面向目标.pdf"); } catch(NullPointerException e) { }*/ /*try { FileInputStream fis = new FileInputStream("D:curse2-JavaSEdocumentJavaSE进阶讲义JavaSE进阶-01-面向目标.pdf"); System.out.println("以上呈现反常,这儿无法履行!"); } catch(FileNotFoundException e) { System.out.println("文件不存在!"); } System.out.println("hello world!");*/ /*try { FileInputStream fis = new FileInputStream("D:curse2-JavaSEdocumentJavaSE进阶讲义JavaSE进阶-01-面向目标.pdf"); } catch(IOException e) { // 多态:IOException e = new FileNotFoundException(); System.out.println("文件不存在!"); }*/ /*try { FileInputStream fis = new FileInputStream("D:curse2-JavaSEdocumentJavaSE进阶讲义JavaSE进阶-01-面向目标.pdf"); } catch(Exception e) { // 多态:Exception e = new FileNotFoundException(); System.out.println("文件不存在!"); }*/ /*try { //创立输入流 FileInputStream fis = new FileInputStream("D:curse2-JavaSEdocumentJavaSE进阶讲义JavaSE进阶-01-面向目标.pdf"); //读文件 fis.read(); } catch(Exception e) { //所有的反常都走这个分支。 System.out.println("文件不存在!"); }*/ /*try { //创立输入流 FileInputStream fis = new FileInputStream("D:curse2-JavaSEdocumentJavaSE进阶讲义JavaSE进阶-01-面向目标.pdf"); //读文件 fis.read(); } catch(FileNotFoundException e) { System.out.println("文件不存在!"); } catch(IOException e){ System.out.println("读文件报错了!"); }*/ // 编译报错。 /* try { //创立输入流 FileInputStream fis = new FileInputStream("D:curse2-JavaSEdocumentJavaSE进阶讲义JavaSE进阶-01-面向目标.pdf"); //读文件 fis.read(); } catch(IOException e){ System.out.println("读文件报错了!"); } catch(FileNotFoundException e) { System.out.println("文件不存在!"); } */ // JDK8的新特性! try { //创立输入流 FileInputStream fis = new FileInputStream("D:curse2-JavaSEdocumentJavaSE进阶讲义JavaSE进阶-01-面向目标.pdf"); // 进行数学运算 System.out.println(100 / 0); // 这个反常是运行时反常,编写程序时能够处理,也能够不处理。 } catch(FileNotFoundException | ArithmeticException | NullPointerException e) { System.out.println("文件不存在?数学反常?空指针反常?都有或许!"); } } }
反常目初始化英文标的两个重要办法
获取反常简略的描述信息: String msg = exception.getMessage(); 打印反常追踪的堆栈信息: exception.printStackTrace();
实例
public class ExceptionTest08 { public static void main(String[] args) { // 这儿仅仅为了测验getMessage()办法和printStackTrace()办法。 // 这儿仅仅new了反常目标,可是没有将反常目标抛出。JVM会以为这是一个普通的java目标。 NullPointerException e = new NullPointerException("空指针反常fdsafdsafdsafds"); // 获取反常简略描述信息:这个信息实践上便是结构办法上面String参数。 String msg = e.getMessage(); //空指针反常fdsafdsafdsafds System.out.println(msg); // 打印反常堆栈信息 // java后台打印反常堆栈追踪信息的时分,选用了异步线程的办法打印的。 e.printStackTrace(); for(int i = 0; i < 1000; i++){ System.out.println("i = " + i); } System.out.println("Hello World!"); } } 运行成果如下:
怎样检查反常并做处理
import java.io.FileInputStream;
import java.io.FileNotFoundException;
/*
咱们今后检查反常的追踪信息,咱们应该怎样看,能够快速的调试程序呢?
反常信息追踪信息,从上往下一行一行看。
可是需求留意的是:SUN写的代码就不用看了(看包名就知道是自己的仍是SUN的。)。
首要的问题是呈现在自己编写的代码上。
*/
public class ExceptionTest09 {
public static void main(String[] args) {
try {
m1();
} catch (FileNotFoundException e) {
// 获取反常的简略描述信息
String msg = e.getMessage();
System.out.println(msg); //C:jetns-agent.jar (体系找不到指定的文件。)
//打印反常堆栈追踪信息!!!
//在实践的开发中,主张运用这个。养成好习惯!
// 这行代码要写上,不然出问题你也不知道!
//e.printStackTrace();
/*
java.io.FileNotFoundException: C:jetns-agent.jar (体系找不到指定的文件。)
at java.base/java.io.FileInputStream.open0(Native Method)
at java.base/java.io.FileInputStream.open(FileInputStream.java:213)
at java.base/java.io.FileInputStream.<init>(FileInputStream.java:155)
at java.base/java.io.FileInputStream.<init>(FileInputStream.java:110)
at com.bjpowernode.javase.exception.ExceptionTest09.m3(ExceptionTest09.java:31)
at com.bjpowernode.javase.exception.ExceptionTest09.m2(ExceptionTest09.java:27)
at com.bjpowernode.javase.exception.ExceptionTest09.m1(ExceptionTest09.java:23)
at com.bjpowernode.javase.exception.ExceptionTest09.main(ExceptionTest09.java:14)
由于31行出问题导致了27行
27行出问题导致23行
23行出问题导致14行。
应该先检查31行的代码。31行是代码过错的根源。
*/
}
// 这儿程序不耽误履行,很强健。《服务器不会由于遇到反常而宕机。》
System.out.println("Hello World!");
}
private static void m1() throws FileNotFoundException {
m2();
}
private static void m2() throws FileNotFoundException {
m3();
}
private static void m3() throws FileNotFoundException {
new FileInputStream("C:jetns-agent.jar");
}
}
Finally句子
"1、在finally子句中的代码是终究履行的,并且是必定会履行的,即便try句子块中的代码呈现了反常。 finally子句有必要和try一同呈现,不能独自编写。 "2、finally句子通常运用在哪些状况下呢? 通常在finally句子块中完结资源的释放/封闭。 由于finally中的代码比较有保证。 即便try句子块中的代码呈现反常,finally中代码也会正常履行。
实例
public class ExceptionTest10 { public static void main(String[] args) { FileInputStream fis = null; // 声明方位放到try外面。这样在finally中才能用。 try { // 创立输入流目标 fis = new FileInputStream("D:course2-JavaSEdocumentJavaSE进阶讲义JavaSE进阶-01-面向目标.pdf"); // 开端读文件.... String s = null; // 这儿必定会呈现空指针反常! s.toString(); System.out.println("hello world!"); // 流运用完需求封闭,由于流是占用资源的。 // 即便以上程序呈现反常,流也有必要要封闭! // 放在这儿有或许流关不了。 //fis.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch(IOException e){ e.printStackTrace(); } catch(NullPointerException e) { e.printStackTrace(); } finally { System.out.println("hello 浩克!"); // 流的封闭放在这儿比较稳妥。 // finally中的代码是必定会履行的。 // 即便try中呈现了反常! if (fis != null) { // 防止空指针反常! try { // close()办法有反常,选用捕捉的办法。 fis.close(); } catch (IOException e) { e.printStackTrace(); } } } System.out.println("hello kitty!"); } }
Try和finally的连用
验证finally句子必定是终究履行的
public class ExceptionTest11 { public static void main(String[] args) { /* try和finally,没有catch能够吗?能够。 try不能独自运用。 try finally能够联合运用。 以下代码的履行次序: 先履行try... 再履行finally... 终究履行 return (return句子只需履行办法必定完毕。) */ try { System.out.println("try..."); return; } finally { // finally中的句子会履行。能履行到。 System.out.println("finally..."); } // 这儿不能写句子,由于这个代码是无法履行到的。 //System.out.println("Hello World!"); } }
关于Finally中的特例
"留意,当退出JVM的时分,Finally句子就不会履行了" public class ExceptionTest12 { public static void main(String[] args) { try { System.out.println("try..."); // 退出JVM System.exit(0); // 退出JVM之后,finally句子中的代码就不履行了! } finally { System.out.println("finally..."); } } }
Finally易错点
"试推测下列result的返回值 public class Test { public static void main(String[] args) { int result = m(); System.out.println(result); //猜测成果 } public static int m(){ int i = 100; try { return i; } finally { i++; System.out.println("Finally中的i"+i); } } }
分析
"java语法规矩(有一些规矩是不能破坏的,一旦这么说了,就有必要这么做!): java中有一条这样的规矩: 办法体中的代码有必要遵循自上而下次序依次逐行履行(亘古不变的语法!) java中还有一条语法规矩: return句子一旦履行,整个办法有必要完毕(亘古不变的语法!)
运行成果
能够看出,虽然finally句子块履行了,可是,return的值仍是100!! 为什么?看看反编译的成果 public static int m(){ int i = 100; int j = i; i++; return j; } "不难看出,在反编译的时分,引入了一个新的中心变量,来处理咱们的疑问
Final 、Finally、 Finalize的差异
"final 关键字 final润饰的类无法承继 final润饰的办法无法掩盖 final润饰的变量不能从头赋值。 "finally 关键字 和try一同联合运用。 finally句子块中的代码是有必要履行的。 "finalize 标识符 是一个Object类中的办法名。 这个办法是由废物收回器GC担任调用的。
实例
public class ExceptionTest14 { public static void main(String[] args) { // final是一个关键字。表示终究的。不变的。 final int i = 100; //i = 200; // finally也是一个关键字,和try联合运用,运用在反常处理机制中 // 在fianlly句子块中的代码是必定会履行的。 try { } finally { System.out.println("finally...."); } // finalize()是Object类中的一个办法。作为办法名呈现。 // 所以finalize是标识符。 // finalize()办法是JVM的GC废物收回器担任调用。 Object obj; } } // final润饰的类无法承继 final class A { // 常量。 public static final double MATH_PI = 3.1415926; } class B { // final润饰的办法无法掩盖 public final void doSome(){ } }
自定义的生产异常处理反常类
Java中怎样自定义反常呢? 两步: "榜首步:编写一个类承继Exception或许RuntimeException. "第二步:供给两个结构办法,一个无参数的,一个带有String参数的。
实例
public class MyException extends Exception{ // 编译时反常 public MyException(){ } public MyException(String s){ super(s); } }
反常的归纳实例
编写程序,运用一维数组,模仿栈数据结构。 要求: 1、这个栈能够存储java中的任何引证类型的数据。 2、在栈中供给push办法模仿压栈。(栈满了,要有提示信息。) 3、在栈中供给pop办法模仿弹栈。(栈空了,也有有提示信息。) 4、编写测验程序,new栈目标,调用push pop办法来模仿压栈弹栈的动作。 5、假设栈的默认初始化容量是10.(请留意无参数结构办法的编写办法。)
自定义反常办法
public class StackException extends Exception{ public StackException(){ } public StackException(String s){ super(s); } }
测验类
import java.util.ArrayList;
import java.util.List;
public class Test {
static int temp = 0;
public static void main(String[] args) {
// 创立一个调集目标并指定其初始容量
List<Object> mylist = new ArrayList<Object>(10);//自定义栈的初始容量为10
// 创立一个本类的目标,便利来调用下面的实例办法
Test test = new Test();
// 模仿压栈
test.push(mylist,1);
test.push(mylist,2);
test.push(mylist,3);
test.push(mylist,4);
// 模仿弹栈
test.pop(mylist);
test.pop(mylist);
test.pop(mylist);
test.pop(mylist);
}
//压栈办法
public void push(List list,Object object){
if(temp <= 9){
list.add(temp,object);
System.out.println("添加元素"+object+"成功!");
temp++;
}else{
try {
throw new StackException("添加元素"+object+"失利,栈已满!!!");
} catch (StackException e) {
e.printStackTrace();
}
}
}
// 弹栈办法
public void pop (List list){
if(temp > 0){
Object o1 = list.get(temp-1);
list.remove(temp-1);
System.out.println("删去元素"+o1+"成功!!!");
temp--;
}else{
try {
throw new StackException("弹栈失利,栈已空!!!");
} catch (StackException e) {
e.printStackTrace();
}
}
}
}
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。
评论(0)