java try catch 例子_java try catch

try catch机制非常好。那些觉得try catch不行的人,是他们自己的水平有问题,无法理解这种机制。并且这群人写代码不遵守规则,喜欢偷懒,这才造成try catch不好的错觉。

详细解释:

1.程序要健壮,必须要设计报错机制。

最古老,也是最常见的,比如:

bool CreateFile( );

//如果创建文件失败就返回false,否则返回true。

这种报错方式,显然不好。因为它没有给出产生错误的具体原因。

2.改进:一个函数或过程,会因为不同的原因产生错误,报错机制必须要把这些错误原因进行区分后,再汇报。

比如:

int CreateFile():

//如果创建成功就返回1.

//如果是因为没有权限,导致失败,返回-1。

//如果是因为文件已经存在,导致失败,返回-2。

//如果是因为创建文件发生超时,导致失败,返回-3。

这样看上去,比【1】要好些,至少指出了比较具体的失败原因,但是,还不够。

3.很多情况下,函数需要把详细的原因,用字符串的方式,返回:

class Result

{

....int State;//同【2】

....string ErrorMessage;//如果失败,这里将给出详细的信息,如果有可能,应该把建议也写上去。

}

Result CreateFile();

//如果创建成功,返回的Result,State为1,ErrorMessage为null。

//如果是因为没有权限,导致失败,返回的Result,State为-1,ErrorMessage为"用户【guest】没有权限在【C:\】这个目录下创建该文件。建议您向管理员申请权限,或者更换具有权限的用户。"。

//如果是因为文件已经存在,导致失败,返回的Result,State为-2,ErrorMessage为"文件【C:\abc.txt】已经存在。如果需要覆盖,请添加参数:arg_overwrite = true"。

//如果是因为创建文件发生超时,导致失败,返回的Result,State为-3,ErrorMessage为"在创建文件时超时,请使用chkdsk检查文件系统是否存在问题。"。

4.我个人推崇上面这种方式,完整,美观。但是这种流程,容易与正常的代码混在一起,不好区分开。因此,Java、C#等设计了try catch这一种特殊的方式:

void CreateFile()

//如果创建成功就不会抛出异常。

//如果是因为没有权限,导致失败,会抛出AccessException,这个Exception的Msg属性为"用户【guest】没有权限在【C:\】这个目录下创建该文件。建议您向管理员申请权限,或者更换具有权限的用户。"。

//如果是因为文件已经存在,导致失败,会抛出FileExistedException,这个Exception的Msg属性为"文件【C:\abc.txt】已经存在。如果需要覆盖,请添加参数:arg_overwrite = true"。

//如果是因为创建文件发生超时,导致失败,会抛出TimeoutException,这个Exception的Msg属性为"在创建文件时超时,请使用chkdsk检查文件系统是否存在问题。"。

可见,上述机制,实际上是用不同的Exception代替了【3】的State。

这种机制,在外层使用时:

try

{

....CreateFile( "C:\abc.txt" );

}

catch( AccessException e )

{

....//代码进入这里说明发生【没有权限错误】

}

catch( FileExistedException e )

{

....//代码进入这里说明发生【文件已经存在错误】

}

catch( TimeoutException e )

{

....//代码进入这里说明发生【超时错误】

}

对比一下【3】,其实这与【3】本质相同,只是写法不同而已。

5.综上,我个人喜欢【3】这类面向过程的写法。但很多喜欢面向对象的朋友,估计更喜欢【4】的写法。然而【3】与【4】都一样。这两种机制都是优秀的错误处理机制。

6.理论说完了,回到正题,题注问:为什么不用try catch?

答:这是因为,很多菜鸟,以及新手,他们是这样写代码的:

void CreateFile( )

//无论遇到什么错误,就抛一个 Exception,并且也不给出Msg信息。

这样的话,在外层只能使用:

try

{

....CreateFile( "C:\abc.txt" );

}

catch( Exception e )

{

....//代码进入这里说明发生错误

}

当出错后,只知道它出错了,并不知道是什么原因导致错误。这同【1】。

以及,即使CreateFile是按【4】的规则设计的,但菜鸟在外层是这样使用的:

try

{

....CreateFile( "C:\abc.txt" );

}

catch( Exception e )

{

....//代码进入这里说明发生错误

....throw Exception( "发生错误" )

}

这种情况下,如果这位菜鸟的同事,调用了这段代码,或者用户看到这个错误信息,也只能知道发生了错误,但并不清楚错误的原因。这与【1】是相同的。

出于这些原因,菜鸟的同事,以及用户,并没有想到,造成这个问题是原因菜鸟的水平太差,写代码图简单省事。他们却以为是try catch机制不行。

因此,这就导致了二逼同事,以及傻比用户,不建议用try catch。

通常try/catch适用于以下场景:

在代码中对可预见而又无法掌控的情况进行处理。比如在SOCKET BIND时发现端口已经被占用了、或者IO在打开文件时发现文件不存在,就需要在catch中做适当的处理避免程序crash掉;

将问题向更上一层面传递,将处理权让渡给caller。假如你写了个ORM FRAMEWORK,在delete的时候发现外键关联删除失败,FRAMEWORK不能擅自替上层的代码决定该怎么办,于是只好把DB的报的错误原样(或者加层外衣)throw出来,调用者根据业务需要选择处理方式;

除此之外,所有问题应该由程序员主动判断,就地解决。在规模比较大的软件中,定义自己的Exception体系并正确、克制地使用try/catch,可以让代码变得易读易维护还美观。

传递给上层来解决例子如下:

void handlearray(int a[]) throws Npe

{

if(a==null)

throw new Npe();

a[0]……//处理部分

}

上层:

try{

handlearray(a);

}catch(E… e)

{

//对a进行处理。

}

这时候传入数组为空,这个错误不是你当前这个函数所能处理的,只能是抛给上层,也就是生成这个数组,或者能对这个数组负责的那部分代码,让上层去处理,上层去try cacth,并在catch中对异常处理,类库中类似的像文件io的时候很多读写类都会抛出FileNotFoundException,也是一个道理,当上层给我一个找不到的文件,那在我的io类中肯定无法处理你这个异常,只能抛到给我这个文件的那一层,让那一层的代码对这个问题进行反应。

当然有些时候不需要,比如:

void makearray(int a[])

{

a=new int[];

……//生成部分

if(a==null)

……//处理部分,此处一般不用抛异常,直接可以在这一层处理掉。

}

像这个就不一样了,因为这次发生的问题是在我这一层代码所能控制之内的,所以我直接把问题处理掉就好了,没必要给上层了。

为什么讲“正确”并“克制”地使用?因为有些又蠢又懒的程序员喜欢这么干:

将函数所有代码都放到try{}之中,哪怕 int i = 1这种赋值的都不放过。然后在catch里输出一个错误信息就万事大吉。这样看起来是很省心哇,不用动脑子去分析哪里可能发生什么错误,反正所有错误都在catch的掌控之中;

用try/catch来控制流程。举个简单的例子,假设有这么个要求:

将字符串转换成数字,并返回该数字的绝对值,如果出错了就返回-1. 于是乎,就能见到类似下面代码的奇葩做法:

int parse_number(const char* s){

try{

return abs(atoi(s));

}catch(Exception){

return -1;

}

}

这多省事儿,不用考虑s是不是NULL、不用考虑s是不是包含非数字的字符、不用考虑s是不是超出int的取值范围...我是个优秀的程序员耶~~,我的代码好简洁。

try/catch和errno可以结合起来使用,二者不是非此即彼的关系,比如在某些场景下,可以将不确定的错误简化归纳为固定的errno输出,调用者直接检查返回的errno即可,简化了代码,也减轻了负担。比如某函数,成功返回0,失败返回-1:

int foo(double d){

try{

do_something(d);

return 0;

}catch(Exception){

return -1;

}

}

void bar(double d){

int result = foo(d);

if(result == -1) return;

do_next_steps();

}

三、细节

Java中try,catch,finally的用法

Java异常处理的组合方式:

1.try+catch

运行流程:运行到try块中,如果有异常抛出,则转到catch块去处理。然后执行catch块后面的语句

2.try+catch+finally

运行流程:运行到try块中,如果有异常抛出,则转到catch块,catch块执行完毕后,执行finally块的代码,再执行finally块后面的代码。

如果没有异常抛出,执行完try块,也要去执行finally块的代码。然后执行finally块后面的语句

网上有很多人探讨Java中异常捕获机制try...catch...finally块中的finally语句是不是一定会被执行?很多人都说不是,当然他们的回答是正确的,经过我试验,至少有两种情况下finally语句是不会被执行的:

(1)try语句没有被执行到,如在try语句之前就返回了,这样finally语句就不会执行,这也说明了finally语句被执行的必要而非充分条件是:相应的try语句一定被执行到。

(2)在try块中有System.exit(0);这样的语句,System.exit(0);是终止Java虚拟机JVM的,连JVM都停止了,所有都结束了,当然finally语句也不会被执行到。

四、检查型异常和非检查型异常

8f8e0178f886

Paste_Image.png

上图摘自Java 进阶 之 检查型异常与非检查型异常

直接继承 Exception 的异常,属于检查型异常,必须用try语句块进行处理或者把异常交给上级方法处理总之就是必须写代码处理它。如IOException,SQLException

继承自Runtime Exception或 Error 的是非检查型异常,可以不用捕获

1、throws出现在方法函数头;而throw出现在函数体。

2、throws表示出现异常的一种可能性,并不一定会发生这些异常;throw则是抛出了异常,执行throw则一定抛出了某种异常对象。

3、两者都是消极处理异常的方式(这里的消极并不是说这种方式不好),只是抛出或者可能抛出异常,但是不会由函数去处理异常,真正的处理异常由函数的上层调用处理。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/501628.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JAVA入门级教学之(布尔型数据类型)

/* 关于布尔型数据类型: boolean 在java语言中boolean类型只有两个值:true、false,没有其它值 不像c语言中,0和1可以表示假和真 在底层存储的时候boolean类型占用1个字节,因为实际存储的时候false底层是0,true底层是1…

java 自动生成文档_[原]java开发文档的自动生成方式

对于Java注释我们主要了解三种:// 注释一行/* ...... */ 注释若干行第三种,文档注释:/** ...... */ 注释若干行,并写入 javadoc 文档通常这种注释的多行写法如下:/*** .........* .........*/很多人多忽视了这第三种注…

JAVA入门级教学之(数据转换规则)

/* 关于基本数据之间的互相转换&#xff1a;转换规则 1、八种基本数据类型中**除布尔类型之外**剩下的7种类型之间都可以互相转换2、小容量向大容量转换&#xff0c;称为自动类型转换&#xff0c;容量从小到大排序如下&#xff1a;-byte<short<int<long <float<…

java程序员面试技术_java程序员面试应该具备的一些基本技能

这里列举一些Java程序员面试应该要具备的一些基本技能&#xff0c;仅当参考。1.基本语法包括static、final、transient等关键字的作用&#xff0c;foreach循环的原理等等。越简单的问题越能看出一个人的水平&#xff0c;别人对你技术的考量绝大多数都是以深度优先、广度次之为标…

JAVA入门级教学之(算数运算符)

/*3.运算符 *算数运算符 *关系运算符 *逻辑运算符 *字符串连接运算符 *三元运算符 *赋值类运算符 */ /* 关于java编程中运算符之&#xff1a;算数运算符 求和 - 相减 * 乘积 / 商 % 求余取模 自加1 -- 自减1 注意&#xff1a;一个表达式中如果有多个运算符&#xf…

web api教程Java_WebApi项目创建CURD

WebApi1.创建实体类public class Contact{public string Id { get; set; }public string Name { get; set; }public string Phone { get; set; }public string Email { get; set; }public DateTime LastModified { get; set; }}2.操作实体类接口public interface IContactRepos…

JAVA入门级教学之(关系运算符)

/* 关系运算符&#xff1a;比较的是两个变量保存的值的大小 大于 大于等于 < 小于 < 小于等于 等于 &#xff01; 不等于 是赋值运算符 是关系运算符 关系运算符的运行结果一定是布尔类型&#xff1a;true/false */ public class OperatorTest02 {public static v…

guid java_JAVA实现生成GUID的方法

JAVA实现生成GUID的方法GUID是一个128位长的数字&#xff0c;一般用16进制表示。算法的核心思想是结合机器的网卡、当地时间、一个随即数来生成GUID。从理论上讲&#xff0c;如果一台机器每秒产生10000000个GUID&#xff0c;则可以保证(概率意义上)3240年不重复。复制代码 代码…

JAVA入门级教学之(逻辑(布尔)运算符)

/*逻辑(布尔)运算符&#xff1a; & 逻辑与 (两边的算子都是true&#xff0c;结果才是true) | 逻辑或 (两边的算子只要有一个是true&#xff0c;结果就是true) ! 逻辑非 (取反) ^ 逻辑异或(两边的算子只要是不一样的&#xff0c;结果就是reue) && 短路与 ||…

JAVA入门级教学之(赋值运算符)

/* 赋值运算符 字符串连接运算符 三目运算符/三元运算符/条件运算符 关于JAVA中的赋值类运算符&#xff1a; 赋值类运算符包括两种&#xff1a; *基本的赋值运算符 *扩展的赋值运算符 - * / % 1.赋值类的运算符优先级&#xff1a;先执行等…

java xss 默认值_一台 Java 服务器可以跑多少个线程?

原标题&#xff1a;一台 Java 服务器可以跑多少个线程&#xff1f;转自&#xff1a;简书&#xff0c;作者&#xff1a;新栋BOOK一台Java服务器能跑多少个线程&#xff1f;这个问题来自一次线上报警如下图&#xff0c;超过了我们的配置阈值。京东自研UMP监控分析打出jstack文件&…

mysql引擎inndbmmyisam_Mysql中MyISAM引擎和InnoDB引擎的比较

结论如果不清楚自己应该用什么引擎&#xff0c;那么请选择InnoDB&#xff0c;Mysql5.5的版本默认引擎都是InnoDB&#xff0c;早期的Mysql版本默认的引擎是MyISAMMyISAM 和 InnoDB的适用场景MyISAM适合&#xff1a;(1)做很多count 的计算&#xff1b;(2)插入不频繁&#xff0c;查…

JAVA入门级教学之(连接运算符)

/*关于字符串的连接运算符 关于java中的""运算符&#xff1a; 1.加号运算符在java语言中有两个作用&#xff1a; *加法运算&#xff0c;求和 *字符串的连接运算 2.当""运算符两边的数据都是数字的话&#xff0c;一定是进行加法运算。 3.当"…

java android aes加密解密_AES加密解密在JAVA和ANDROID下互通

昨天外包安卓的那个人说AES的加解密结果不一样。于是百度搜索发现还真是!贴上AES加密核心&#xff1a;Cipher cipher Cipher.getInstance("AES/CBC/PKCS5Padding");cipher.init(Cipher.ENCRYPT_MODE, key, zeroIv);CBC是工作模式&#xff0c;AES一共同拥有电子passw…

JAVA入门级教学之(三元运算符)

/* 三元运算符/三目运算符/条件运算符 1.语法规则&#xff1a; 布尔表达式?表达式1:表达式2; true 执行表达式1 false 执行表达式2 */ public class OperatorTest06 {public void main(String[] args) { //编译错误 //10; //男;//布尔类型的变量 boolean sexf…

java 加密 数字_java 加密数字签名

1)消息摘要&#xff1a;这是一种与消息认证码结合使用以确保消息完整性的技术。 主要使用单向散列函数算法&#xff0c;可用于检验消息的完整性&#xff0c;和通过散列密码直接以文本形式保存等&#xff0c;目前广泛使用的算法有MD4、MD5、SHA- 1&#xff0c;jdk1.5对上面都提供…

JAVA入门级教学之(if语句)

/* 关于java语言中的if语句&#xff0c;属于选择结构 if语句又被称为分支语句/条件控制语句1.if语句的语法结构&#xff1a;四种编写方式 第一种&#xff1a;条件为真&#xff0c;执行大括号内容 条件为假&#xff0c;*跳出*大括号内容 if(布尔表达式){ java…

python怎么处理数据标注_在python中将数据标记为敏感

编辑我提出了一个使用ctypes(反过来使用c)将内存归零的解决方案。import sysimport ctypesdef zerome(string):location id(string) 20size sys.getsizeof(string) - 20memset ctypes.cdll.msvcrt.memset# For Linux, use the following. Change the 6 to whatever it is o…

JAVA入门级教学之(switch语句)

/* 关于switch语句(我称为匹配语句)&#xff1a; 1.switch语句也属于选择结构&#xff0c;也是分支语句 2.switch语句的语法结构&#xff1a; 一个比较完整的switch语句应该这样编写&#xff1a; //case有匹配的意思,相当于拿数据匹配&#x…

java实现验证码图片_java实现验证码图片

1 packagesip.utils;2 importjava.awt.Color;3 importjava.awt.Graphics2D;4 importjava.awt.geom.AffineTransform;5 importjava.util.Random;67 /**8 * 验证码图片生成器9 *10 *authorWuZhengFei11 *12 */13 public classIdentityCode {14 /**15 * 验证码图片的宽度。16 */17…