【java基本之非常】死了都要try,不极尽描摹地catch我不愉快!
2019-11-18杂谈搜奇网37°c
A+ A-目次
- 1、非常
- 1.1 非常观点
- 1.2 非常系统
- 1.3 非常分类
- 1.4 非常的发作历程剖析
- 2、 非常的处置惩罚
- 2.1 抛出非常throw
- 2.2 Objects非空推断
- 2.3 声明非常throws
- 2.4 捕捉非常try…catch
- 2.4 finally 代码块
- 2.5 finally 代码块与return语句
- 2.6 非常注重事项
- 3、自定义非常
- 3.1 概述
- 3.2 自定义非常演习
- 4、来!和非常大干一场
@
1、非常
1.1 非常观点
非常 :简朴说就是不正常运转,终究致使JVM的非正常住手。
在Java等面向对象的编程语言中,非常本身是一个类,发作非常就是建立非常对象并抛出了一个非常对象。Java处置惩罚非常的体式格局是中断处置惩罚。
非常指的并非语法毛病,语法错了,编译不经由过程,不会发作字节码文件,基本不能运转.
1.2 非常系统
非常机制现实上是协助我们找到顺序中的题目,非常的根类是java.lang.Throwable
,其下有两个子类:java.lang.Error
与java.lang.Exception
,寻常所说的非常指java.lang.Exception
。
Throwable中的经常运用要领:
1、 public void printStackTrace()
:打印非常的详细信息。
包含了非常的范例,非常的缘由,还包含非常涌现的位置,在开辟和调试阶段,都得运用printStackTrace。
2、 public String getMessage()
:猎取发作非常的缘由。
提示给用户的时刻,就提示毛病缘由。
3、 public String toString()
:猎取非常的范例和非常形貌信息(不必)。
涌现非常,最简朴的体式格局就是把非常的简朴类名,拷贝到API中去查。
1.3 非常分类
我们寻常说的非常就是指Exception
,由于这类非常一旦涌现,我们就要对代码举行改正,修复顺序。
非常(Exception)的分类:依据在编译时代照样运转时代去搜检非常?
- 编译时代非常:checked非常。在编译时代,就会搜检,假如没有处置惩罚非常,则编译失利。(如日期花样化非常)
- 运转时代非常:runtime非常。在运转时代,搜检非常.在编译时代,运转非常不会编译器检测(不报错)。(如数学非常)
1.4 非常的发作历程剖析
先运转下面的顺序,顺序会发作一个数组索引越界非常ArrayIndexOfBoundsException
。我们经由过程图解来剖析下非常发作的历程。
东西类
public class ArrayTools {
// 对给定的数组经由过程给定的角标猎取元素。
public static int getElement(int[] arr, int index) {
int element = arr[index];
return element;
}
}
测试类
public class ExceptionDemo {
public static void main(String[] args) {
int[] arr = { 34, 12, 67 };
intnum = ArrayTools.getElement(arr, 4)
System.out.println("num=" + num);
System.out.println("over");
}
}
上述顺序实行历程图解:
2、 非常的处置惩罚
Java非常处置惩罚的五个关键字:try
、catch
、finally
、throw
、throws
2.1 抛出非常throw
在编写顺序时,作为一个优异的顺序员必需要斟酌顺序涌现题目的状况。举个栗子,在定义要领时,要领须要接收参数。那末,当挪用要领运用接收到的参数时,起首须要先对参数数据举行正当的推断,数据若不正当,就应该通知挪用者,通报正当的数据进来。这时候须要运用抛出非常的体式格局来通知挪用者。这个时刻throw就派上用场了!
在java中,供应了一个throw关键字,Throw用来抛出一个指定的非常对象。从而可以
1、建立一个非常对象。封装一些提示信息(信息可以本身编写)。
2、经由过程关键字
throw
就可以将这个非常对象示知给挪用者,还可以将这个非常对象通报到挪用者处。
throw小结
throw
用在要领内,背面接一个非常对象,运用花样为throw new 非常类名(参数);
,将这个非常对象通报到挪用者处,并完毕当前要领的实行。
throw运用的花样以下:
~~~java
throw new NullPointerException("要接见的arr数组不存在");
throw new ArrayIndexOutOfBoundsException("该索引在数组中不存在,已超出范围");
~~~
运用throw的实例运用:
public class ThrowDemo {
public static void main(String[] args) {
//建立一个数组
int[] arr = {2,4,52,2};
//依据索引找对应的元素
int index = 4;
int element = getElement(arr, index);
System.out.println(element);
System.out.println("over");
}
/*
* 依据 索引找到数组中对应的元素
*/
public static int getElement(int[] arr,int index){
//推断 索引是不是越界
if(index<0 || index>arr.length-1){
/*
推断前提假如满足,当实行完throw抛出非常对象后,要领已没法继续运算。
这时候就会完毕当前要领的实行,并将非常示知给挪用者。这时候就须要经由过程非常来处理。
*/
throw new ArrayIndexOutOfBoundsException("哥们,角标越界了~~~");
}
int element = arr[index];
return element;
}
}
throw
运转效果剖析:
再来看看不运用throw的实例运用的运转:
public static void main(String[] args) {
//建立一个数组
int[] arr = {2,4,52,2};
//依据索引找对应的元素
int index = 4; //注重索引4已越界了
int ele=arr[index];
System.out.println(ele);
System.out.println("over");
}
运转效果
如许一对照throw
的上风就显而易见了~
2.2 Objects非空推断
还记得Objects
类吗,曾提到过它由一些静态的有用要领构成,这些要领是null-save
(空指针平安的)或null-tolerant
(容忍空指针的),那末在它的源码中,对对象为null的值举行了抛出非常操纵。
public static <T> T requireNonNull(T obj)
:检察指定援用对象不是null。
检察源码发明这里对为null的举行了抛出非常操纵:
public static <T> T requireNonNull(T obj) {
if (obj == null)
throw new NullPointerException();
return obj;
}
2.3 声明非常throws
假如发作了题目,我们就会
throw
将题目形貌类即非常举行抛出,也就是将题目返回给该要领的挪用者。那末关于挪用者来讲,该如何处置惩罚呢?一种是举行捕捉处置惩罚,另一种就是继续讲题目声明出去,运用
throws
声明处置惩罚。
声明非常:将题目标识出来,报告给挪用者。假如要领内经由过程throw抛出了编译时非常,而没有捕捉处置惩罚(稍后解说该体式格局),那末必需经由过程throws举行声明,让挪用者去处置惩罚。
throws小结
关键字throws运用于要领声明之上,throws
花样为修饰符 返回值范例 要领名(参数) throws 非常类名1,非常类名2…{ }
,用于示意当前要领不处置惩罚非常,而是提示该要领的挪用者来处置惩罚非常(抛出非常).
声明非常的代码演示:
public class ThrowsDemo {
public static void main(String[] args) throws FileNotFoundException {
read("a.txt");
}
// 假如定义功用时有题目发作须要报告给挪用者。可以经由过程在要领上运用throws关键字举行声明
public static void read(String path) throws FileNotFoundException {
if (!path.equals("a.txt")) {//假如不是 a.txt这个文件
// 我假定 假如不是 a.txt 以为 该文件不存在 是一个毛病 也就是非常 throw
throw new FileNotFoundException("文件不存在");
}
}
}
throws
用于举行非常类的声明,若该要领可以有多种非常状况发作,那末在throws
背面可以写多个非常类,用逗号离隔。
public class ThrowsDemo2 {
public static void main(String[] args) throws IOException {
read("a.txt");
}
public static void read(String path)throws FileNotFoundException, IOException {
if (!path.equals("a.txt")) {//假如不是 a.txt这个文件
// 我假定 假如不是 a.txt 以为 该文件不存在 是一个毛病 也就是非常 throw
throw new FileNotFoundException("文件不存在");
}
if (!path.equals("b.txt")) {
throw new IOException();
}
}
}
throw 和 throws 的区分小结
throw:
1、示意要领内抛出某种非常对象
2、假如非常对象是非 RuntimeException
则须要在要领申明时加上该非常的抛出 即须要加上throws
语句 或许 在要领体内try catch
处置惩罚该非常,不然编译报错
3、实行到throw
语句则背面的语句块不再实行
throws:
1、要领的定义上运用
throws
示意这个要领可以抛出某种非常
2、须要由要领的挪用者举行非常处置惩罚
2.4 捕捉非常try…catch
假如非常涌现的话,会马上停止顺序,所以我们得处置惩罚非常:
- 该要领不处置惩罚,而是声明抛出,由该要领的挪用者来处置惩罚(
throws
)。 - 在要领中运用
try-catch
的语句块来处置惩罚非常。
try-catch的体式格局就是捕捉非常。
捕捉非常:Java中对非常有针对性的语句举行捕捉,可以对涌现的非常举行指定体式格局的处置惩罚。
捕捉非常语法以下:
try{
编写可以会涌现非常的代码
}catch(非常范例 e){
处置惩罚非常的代码
//纪录日记/打印非常信息/继续抛出非常
}
try
:该代码块中编写可以发作非常的代码。
catch
:用来举行某种非常的捕捉,完成对捕捉到的非常举行处置惩罚。
注重:
try
和catch
都不能零丁运用,必需连用。
演示以下:
public class TryCatchDemo {
public static void main(String[] args) {
try {// 当发作非常时,必需有处置惩罚体式格局。要么捕捉,要么声明。
read("b.txt");
} catch (FileNotFoundException e) {// 括号中须要定义什么呢?
//try中抛出的是什么非常,在括号中就定义什么非常范例
System.out.println(e);
}
System.out.println("over");
}
/*
*
* 我们 当前的这个要领中 有非常 有编译期非常
*/
public static void read(String path) throws FileNotFoundException {
if (!path.equals("a.txt")) {//假如不是 a.txt这个文件
// 我假定 假如不是 a.txt 以为 该文件不存在 是一个毛病 也就是非常 throw
throw new FileNotFoundException("文件不存在");
}
}
}
如何猎取非常信息:
Throwable类中定义了一些检察要领:
1、 public String getMessage()
:猎取非常的形貌信息,缘由(提示给用户的时刻,就提示毛病缘由。
2、 public String toString()
:猎取非常的范例和非常形貌信息(不必)。
3、 public void printStackTrace()
:打印非常的跟踪栈信息并输出到控制台。
包含了非常的范例,非常的缘由,还包含非常涌现的位置,在开辟和调试阶段,都得运用printStackTrace。
2.4 finally 代码块
finally:有一些特定的代码不论非常是不是发作,都须要实行。别的,由于非常会激发顺序跳转,致使有些语句实行不到。而finally
就是处理这个题目的,在finally
代码块中寄存的代码都是肯定会被实行的。
什么时刻的代码必需终究实行?
当我们在try
语句块中翻开了一些物理资本(磁盘文件/网络衔接/数据库衔接等),我们都得在运用完以后,终究封闭翻开的资本。
finally的语法:
try...catch....finally
:本身须要处置惩罚非常,终究还得封闭资本。
注重:
finally
不能零丁运用。
比如在IO
流中,当翻开了一个关联文件的资本,末了顺序不论效果如何,都须要把这个资本封闭掉。
finally
代码参考以下:
public class TryCatchDemo4 {
public static void main(String[] args) {
try {
read("a.txt");
} catch (FileNotFoundException e) {
//抓取到的是编译期非常 抛出去的是运转期
throw new RuntimeException(e);
} finally {
System.out.println("不论顺序如何,这里都将会被实行。");
}
System.out.println("over");
}
/*
*
* 我们 当前的这个要领中 有非常 有编译期非常
*/
public static void read(String path) throws FileNotFoundException {
if (!path.equals("a.txt")) {//假如不是 a.txt这个文件
// 我假定 假如不是 a.txt 以为 该文件不存在 是一个毛病 也就是非常 throw
throw new FileNotFoundException("文件不存在");
}
}
}
当只要在try或许catch中挪用退出JVM的相干要领,此时finally才不会实行,不然finally永久会实行。
2.5 finally 代码块与return语句
另有个迥殊主要的点就是在try
块或catch
块中碰到return
语句时,finally语句块将在要领返回之前被实行,别的finally
语句中也可以有return
语句,然则只管防止有return
语句(会报正告)
2.6 非常注重事项
多个非常运用捕捉又该如何处置惩罚呢?
多个非常离别处置惩罚。
- 多个非常一次捕捉,屡次处置惩罚。
多个非常一次捕捉一次处置惩罚。
平常我们是运用一次捕捉屡次处置惩罚体式格局,花样以下:
try{
编写可以会涌现非常的代码
}catch(非常范例A e){ 当try中涌现A范例非常,就用该catch来捕捉.
处置惩罚非常的代码
//纪录日记/打印非常信息/继续抛出非常
}catch(非常范例B e){ 当try中涌现B范例非常,就用该catch来捕捉.
处置惩罚非常的代码
//纪录日记/打印非常信息/继续抛出非常
}
注重:这类非常处置惩罚体式格局,请求多个
catch
中的非常不能雷同,而且若catch
中的多个非常之间有子父类非常的关联,那末子类非常请求在上面的catch
处置惩罚,父类非常鄙人面的catch
处置惩罚。
非常注重小结:
运转时非常被抛出可以不处置惩罚。即不捕捉也不声明抛出。
假如
finally
有return
语句,永久返回finally
中的效果,防止该状况. 上面也提到过!假如父类抛出了多个非常,子类重写父类要领时,抛出和父类雷同的非常或许是父类非常的子类或许不抛出非常。
父类要领没有抛出非常,子类重写父类该要领时也不可抛出非常。此时子类发作该非常,只能捕捉处置惩罚,不能声明抛出
3、自定义非常
3.1 概述
为何须要自定义非常类:
Java
中差别的非常类,离别示意着某一种详细的非常状况,在开辟中老是有些非常状况是SUN
没有定义好的,此时我们依据本身营业的非常状况来定义非常类。比方顺序员头发数为负数、小明考试成绩负数题目等等。
在之前顺序代码中,发明这些非常都是JDK内部定义好的,然则现实开辟中也会涌现许多非常,这些非常很可以在JDK中没有定义过,比方顺序员妻子数目为负数、顺序员老王智商为负数题目.那末能不能本身定义非常呢?答案是能滴!
什么是自定义非常类:
在开辟中依据本身营业的非常状况来定义非常类.
自定义一个营业逻辑非常: RegisterException。一个注册非常类。
非常类如何定义:
- 自定义一个编译期非常: 自定义类 并继续于
java.lang.Exception
。 - 自定义一个运转时代的非常类:自定义类 并继续于
java.lang.RuntimeException
。
3.2 自定义非常演习
比如说我们模仿注册操纵,假如用户名已存在,则抛出非常并提示:亲,该用户名已被注册。
起首定义一个上岸非常类RegisterException
:
// 营业逻辑非常
public class RegisterException extends Exception {
/**
* 空参组织
*/
public RegisterException() {
}
/**
*
* @param message 示意非常提示
*/
public RegisterException(String message) {
super(message);
}
}
模仿上岸操纵,运用数组模仿数据库中存储的数据,并供应当前注册账号是不是存在要领用于推断。
public class Demo {
// 模仿数据库中已存在账号
private static String[] names = {"bill","hill","jill"};
public static void main(String[] args) {
//挪用要领
try{
// 可以涌现非常的代码
checkUsername("nill");
System.out.println("注册胜利");//假如没有非常就是注册胜利
}catch(RegisterException e){
//处置惩罚非常
e.printStackTrace();
}
}
//推断当前注册账号是不是存在
//由因而编译期非常,又想挪用者去处置惩罚 所以声明该非常
public static boolean checkUsername(String uname) throws RegisterException {
for (String name : names) {
if(name.equals(uname)){//假如名字在这内里 就抛出上岸非常
throw new RegisterException("亲"+name+"已被注册了!");
}
}
return true;
}
}
用户名不存在,登录胜利,效果剖析以下:
用户名存在,登录失利,效果剖析以下:
4、来!和非常大干一场
本篇文章到这里基本就看完了,博主我也不知道列位吸收了若干,我得对列位们担任鸭,不能讲完就完事了,因而照样以为让列位稳固稳固一下比较好,假如列位可以做出下面这道典范的非常题,申明非常方面的学问对你来讲就没多大题目了,假如以为那里还不是迥殊懂,可以实时通知我,通常看到了都邑第一时间复兴。好了,试想一下下面顺序运转效果是啥~
package com.gx.Expetion;
public class TestException {
public TestException() {
}
boolean testEx() throws Exception {
boolean ret = true;
try {
ret = testEx1();
} catch (Exception e) {
System.out.println("testEx, catch exception");
ret = false;
throw e;
} finally {
System.out.println("testEx, finally; return value=" + ret);
return ret;
}
}
boolean testEx1() throws Exception {
boolean ret = true;
try {
ret = testEx2();
if (!ret) {
return false;
}
System.out.println("testEx1111, at the end of try");
return ret;
} catch (Exception e) {
System.out.println("testEx1111, catch exception");
ret = false;
throw e;
} finally {
System.out.println("testEx1111, finally; return value=" + ret);
return ret;
}
}
boolean testEx2() throws Exception {
boolean ret = true;
try {
int b = 12;
int c;
for (int i = 2; i >= -2; i--) {
c = b / i;
System.out.println("i=" + i);
}
return true;
} catch (Exception e) {
System.out.println("testEx2222, catch exception");
ret = false;
throw e;
} finally {
System.out.println("testEx2222, finally; return value=" + ret);
return ret;
}
}
public static void main(String[] args) {
TestException testException1 = new TestException();
try {
testException1.testEx();
} catch (Exception e) {
e.printStackTrace();
}
}
}
运转效果:
i=2
i=1
testEx2222, catch exception
testEx2222, finally; return value=false
testEx1111, finally; return value=false
testEx, finally; return value=false
假如以为那里还不是迥殊懂,可以实时通知我,通常看到了都邑第一时间复兴!!!
到这里,许多小白同砚照旧木有感遭到博主“死了都要try,不极尽描摹地catch我不愉快!”的谁人feel,对咩?行,博主就满足满足小白的谁人feel,feelfeel一下 ~=感觉感觉一下~
/**
* 把多条数据的ResultSet的效果放到 List<T>中
* @param rs ResultSet效果集
* @param obj java类的class
* @return
*/
public static <T> List<T> getResult(ResultSet rs, Class<T> obj) {
try {
List<T> list = new ArrayList<T>();
//ResultSetMetaData 有关 ResultSet 中列的称号和范例的信息。
ResultSetMetaData metaData = rs.getMetaData();
//猎取总的列数
int count = metaData.getColumnCount();
//遍历ResultSet
while (rs.next()) {
//---建立对象实例
T instance = obj.newInstance();
for (int i = 1; i <= count; i++) {
//---猎取列名
String name = metaData.getColumnName(i);
// 转变列名花样成 java 定名花样 主如果针对 _ 支解的状况 如user_id
name = toJavaField(name);
//---猎取范例
Class<?> type = obj.getDeclaredField(name).getType();
//---猎取setter要领
// 首字母大写
String replace = name.substring(0, 1).toUpperCase() + name.substring(1);
Method setMethod = obj.getMethod("set" + replace, type);
//---推断读取数据的范例
if (type.isAssignableFrom(String.class)) {
setMethod.invoke(instance, rs.getString(i));
} else if (type.isAssignableFrom(int.class) || type.isAssignableFrom(Integer.class)) {
setMethod.invoke(instance, rs.getInt(i));
} else if (type.isAssignableFrom(Boolean.class) || type.isAssignableFrom(boolean.class)) {
setMethod.invoke(instance, rs.getBoolean(i));
} else if (type.isAssignableFrom(Date.class)) {
setMethod.invoke(instance, rs.getDate(i));
}
}
list.add(instance);
}
return list;
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO: handle exception
}
return null;
}
先不说看不看得懂了,以上代码设想反射、泛型、非常~也就是try..catch~ 、String类、jdbc相干的学问,这些学问我大部分都写过文章了,有兴致的小白同砚就直接点蓝色字体进入文章。咳咳...言归正传,有木有发明以上代码中运用的就是一次捕捉屡次处置惩罚体式格局,花样以下:
try{
编写可以会涌现非常的代码
}catch(非常范例A e){ 当try中涌现A范例非常,就用该catch来捕捉.
处置惩罚非常的代码
//纪录日记/打印非常信息/继续抛出非常
}catch(非常范例B e){ 当try中涌现B范例非常,就用该catch来捕捉.
处置惩罚非常的代码
//纪录日记/打印非常信息/继续抛出非常
}
注重:这类非常处置惩罚体式格局,请求多个
catch
中的非常不能雷同,而且若catch
中的多个非常之间有子父类非常的关联,那末子类非常请求在上面的catch
处置惩罚,父类非常鄙人面的catch
处置惩罚。
这已是第二次写到了,所以列位找到不极尽描摹地catch不愉快的feel了咩?
末了,引荐阅读本专栏的下两篇java文章~有兴致的同砚可以相识一下~
【java基本之多态】明白多态的向上向下转型从“妈妈我想吃烤山药”讲起
【java基本】java继续从“我爸是李刚”讲起
迎接列位关注我的民众号,一同讨论手艺,憧憬手艺,寻求手艺...