JAVA系统常见的异常大集合分析
- 格式:pdf
- 大小:165.26 KB
- 文档页数:18
java常见错误以及可能原因集锦java常见错误以及可能原因集锦0、需要标识符a) 不在函数内1、非法表达式开始b) 可能:丢失括号 .2. no data founda) 可能:setInt(1,100)中,没有100这个值3. 找不到符号a) 可能:没导入包4. 指定了无效URLa) 可能:数据库名或IP错误,即连接出错5. 类路径没有找到a) 可能: ClassNotFoundException: oracle.jdbc.driver.OracleDriverb) 原因: 一般是指包名写错,或者没有import包,或者没有在类路径中找到jar文件c) 解决: 没有加载Oracle驱动jar,在.bash_profile中把ojdbc14.jar加进来6. 空指针异常a) 可能: 数据源错误比如数据库名或IP错误7. 不能执行查询a) 可能: 数据库中表的问题,比如列名不存在8. invalid identitya) 可能: 列名出错9. 若在数据库中创建了两个sequence ,运行时出现异常可能是先后执行了多次select 语句,导致与原有的序列号产生冲突10. 表名或列名不存在a) 可能:表不存在或者没有插入数据到表中11. 不支持的类,类的版本错误a) 可能:没有导入jdk5.0,或者编译器仍为1.412. MappingNotFoundExceptiona) Maybe: In the Eclipse Not refersh , or not exist in the dirctory13. HibernateException: /hibernate.cfg.xml not founda) Maybe1: hibernate.cfg.xml not in the root directoryb) Maybe2: Could not parse configuration .c) resolve: database not connect or use another database14. ConstraintViolationExceptiona) Maybe: used a not true database15. 驱动没有找到或者 JDBC Driver not found可能:连接数据库的驱动jar包不存在或者版本不一致,比如将旧的版本换成新的会造成该类错误16. 空指针异常,/doc/e411973287.html,ng.NullPointerExce ptiona) 可能1:数据库连接出错,比如在hibernate.cfg.xml中的数据错误会导致异常。
Java异常(Exception)处理以及常见异常总结⽬录前⾔异常简介异常类型总结前⾔很多事件并⾮总是按照⼈们⾃⼰设计意愿顺利发展的,经常出现这样那样的异常情况。
例如:你计划周末郊游,计划从家⾥出发→到达⽬的→游泳→烧烤→回家。
但天有不测风云,当你准备烧烤时候突然天降⼤⾬,只能终⽌郊游提前回家。
“天降⼤⾬”是⼀种异常情况,你的计划应该考虑到这样的情况,并且应该有处理这种异常的预案。
计算机程序的编写也需要考虑处理这些异常情况。
异常(exception)是在运⾏程序时产⽣的⼀种异常情况,已经成为了衡量⼀门语⾔是否成熟的标准之⼀。
⽬前的主流编程语⾔java也提供了异常处理机制。
异常简介Java中的异常⼜称为例外,是⼀个在程序执⾏期间发⽣的事件,它中断正在执⾏程序的正常指令流。
为了能够及时有效地处理程序中的运⾏错误,必须使⽤异常类,这可以让程序具有极好的容错性且更加健壮。
在 Java 中⼀个异常的产⽣,主要有如下三种原因:1. Java 内部错误发⽣异常,Java 虚拟机产⽣的异常。
2. 编写的程序代码中的错误所产⽣的异常,例如空指针异常、数组越界异常等。
3. 通过 throw 语句⼿动⽣成的异常,⼀般⽤来告知该⽅法的调⽤者⼀些必要信息。
Java 通过⾯向对象的⽅法来处理异常。
在⼀个⽅法的运⾏过程中,如果发⽣了异常,则这个⽅法会产⽣代表该异常的⼀个对象,并把它交给运⾏时的系统,运⾏时系统寻找相应的代码来处理这⼀异常。
我们把⽣成异常对象,并把它提交给运⾏时系统的过程称为拋出(throw)异常。
运⾏时系统在⽅法的调⽤栈中查找,直到找到能够处理该类型异常的对象,这⼀个过程称为捕获(catch)异常。
例 1为了更好地理解什么是异常,下⾯来看⼀段⾮常简单的 Java 程序。
下⾯的⽰例代码实现了允许⽤户输⼊ 1~3 以内的整数,其他情况提⽰输⼊错误。
package io.renren.config;import java.util.Scanner;/*** Created by LiYangYong*/public class TestException {public static void main(String[] args) {System.out.println("请输⼊您的选择:(1~3 之间的整数)");Scanner input = new Scanner(System.in);int num = input.nextInt();switch (num) {case 1:System.out.println("one");break;case 2:System.out.println("two");break;case 3:System.out.println("three");break;default:System.out.println("error");break;}}}正常情况下,⽤户会按照系统的提⽰输⼊ 1~3 之间的数字。
Java中的异常现象一、基本异常异常情形:指引发阻止当前方法或作用域继续执行的问题.普通问题:在当前环境下能得到足够的信息,总能处理这个错误.而异常情形就不同了.发生了异常后,不能继续下去,因为在当前环境下无法获得必要的信息来解决当前的问题.你所能做的就是从当前环境跳出,并且把问题提交给上一级环境,这一动作就是抛出异常.抛出异常所做的动作:1、用new在堆上创建对象.2、当前执行的程序被终止,从当前环境中弹出对象的引用.此时,由异常处理机制接管程序,并开始寻找一个恰当的地方来执行程序.这个地方就是”异常处理程序”,它的任务就是将程序从错误状态中恢复,以使程序要么换一种方式运行,要么继续运行下去.注意:抛出异常是由方法抛出的.异常也是一个类!并用这个类在堆上建立对象.所有的异常类都有两个构造器:1、缺省的构造器Exception();2、带参数的构造器Exception()的括弧中加上参数.注:要定义自己的异常类,必须从已有的异常类继承。
二、捕获异常如果方法要抛出异常,它必须假定异常将被”捕获”并得到处理.异常处理的好处之一:在一个地方编写解决问题的代码,然后在别的地方处理这些代码的错误。
首先什么是”监控区域”?它是一段可能产生异常的代码.并且后面跟着处理这些异常的代码.也就是try{//可能产生异常的语句放在此处!//在此处捕获异常}三、异常处理程序抛出的异常必须处理,这个地方就是异常处理程序.用catch表示.完整的代码如下:try{}catch(type xx){}异常处理也可以有多个catch!异常处理程序必须紧跟在try块之后,异常处理机制将负责搜索同发生异常的第一个相匹配的程序.一旦catch子句结束,则处理程序的查找过程结束.只有匹配的catch子句才能得到执行.四、终止和恢复异常处理有两种模型:终止:一旦异常抛出,就表明错误无法挽回,也不能继续执行.恢复:异常处理程序可以修正错误.然后重新尝试调用出现问题的方法.(解决办法:将出现异常的语句放在while循环中.)终止模型是今后的重点!而不要考虑恢复模型注意:1:main()作为一个方法也可以有异常说明,这里的异常的类型是Exception,它也是所有”被检查的异常”的基类.通过把它传递到控制台,就不必在main()里写try-catch子句了.尽管很方便,但这不是通用的做法.2:java语言中采用try-catch-finally结构处理异常.一个try-catch-finally结构中,必须有try 语句块,catch语句块.finally语句块不是必须的,但至少要两者取其一.如果3个语句块均存在,一定要按照try/catch/finally的顺序排列.3:catch语句块可以有多个,各catch语句块用于捕获不同的异常.如果try块中的语句在执行时发生异常,则执行从该处中断而进入catch块,根据异常的类型进行匹配,顺序在前的catch块优先进行匹配比较,只要该异常是catch中指定的异常类或其子类就匹配成功,进而执行相应的catch中的内容.4:不管在try语句块中是否抛出异常,也不管catch语句块是否捕获到异常,finally语句块中的内容都将继续被执行.注意,即使try语句块中包含return语句,也会先执行完finally语句块中的代码,再执行return语句返回方法值.5:只有执行System.exit()方法或出现Error错误时,finally语句块才不会获得执行而退出程序.6:如果没有异常出现或异常被捕获、处理,则在退出try-catch-finally结构后,会继续执行后续的代码.7:一个方法抛出异常声明时需分两步,第一步在方法名后采用throws语句声明抛出的异常,如果抛出多个异常,则在各个异常间使用逗号分隔.第二步是在方法体内部采用throw语句抛出异常,以便try语句块捕获.8:ng.Throwable类是所有异常和错误的顶层类.Throwable类有两个直接子类ng.Error和ng.Exception.Error类代表编译期和系统错误,程序员不需要处理它,Exception 类是可以从任何标准java类方法中抛出的基本类型异常,也是程序员需要处理的.注意,ng.RuntimeException异常类是由java虚拟机抛出的,不需要程序员处理.五、java标准异常Throwable这个java类被用来表示任何可以作为异常被抛出的类.它可以分Error用来表示编译时和系统错误,Exception是可以被抛出的基本类型.。
JAVA项⽬常⽤异常处理汇总我们在进⾏JAVA项⽬开发时,经常会⾯对⼀些常见的异常处理情况,接下来我会根据课下查阅学习的资料,来进⾏⼀些总结。
1.空指针异常(ng.nullpointerexception)发⽣该情况⼀般是字符串变量未初始化,数组未初始化,类对象未初始化等。
还有⼀种情况是当该对象为空时你并没有判断是否为空值,这个错误我在之前的web习题上犯过,因此为了避免这种情况,除了检查是否初始化之外,如有必要则要加上判断是否为null的if语句。
2.指定的类不存在(ng.ClassNotFoundException)出现这个错误的原因之⼀是缺包,这时只要下载并导⼊相应的包即可;当我们已经把包导⼊的时候,⼜报了这种错误的情况下,就需要开启⾃⼰的编辑器去调整设置了;在使⽤tomcat的时候,先检查lib中是否导⼊了jar。
3.字符串转换为数字异常(ng.NumberFormatException)这个错误就是字符串中出现⾮数字型字符时,转换为数字时发⽣异常;除此之外,如果字符串转换为数字时超过了类型的范围(⽐如string转int和string转double),也会出现这个错误。
解决该问题的⽅法就是在转换之前先对字符串进⾏检查。
4.数组下标越界异常(ng.IndexOutOfBoundsException)顾名思义,你想取的数组元素在数组中并没有定义出来,⽐如定义了⼀个长度为5的数组a,当你想取a[6]元素时肯定会出错。
解决这类问题就是要注意数组的长度,有时候为了减少空间浪费我们会使⽤动态数组构建⽅法,这时在对数组进⾏操作时建议先⽤length获取其数组长度,从⽽规避错误。
5.数学运算异常(ng.ArithmeticException)除数为0时会报出该错误,解决⽅法:避免除数为0。
这个错误解读为“出现异常的运算条件”,除了除数为0的情况之外,可能还有其他的异常情况,届时具体情况具体分析。
java中遇到的问题和解决方案
目录
1. Java中遇到的问题
1.1 内存溢出问题
1.2 死锁问题
2. 解决方案
2.1 内存溢出问题的解决方案
2.2 死锁问题的解决方案
Java中遇到的问题
在Java编程过程中,经常会遇到各种各样的问题,其中两个比较常见的问题是内存溢出和死锁问题。
内存溢出问题是指程序在运行过程中申请的内存超过了系统能够分配给它的内存大小,导致程序崩溃。
这种问题通常发生在程序中频繁创建大量对象或者持续运行时间过长的情况下。
死锁问题则是指多个线程互相持有对方所需要的资源,导致彼此无法继续执行,进而导致程序无法正常运行。
死锁问题通常发生在多线程编程中,处理不当时很容易出现。
解决方案
针对内存溢出问题,可以通过一些方法来解决,比如增加堆内存大小、优化程序代码以减少内存占用、及时释放不再使用的对象等。
另外,可以使用一些工具来监控程序内存使用情况,及时发现并解决潜在的内存溢出问题。
对于死锁问题,可以通过合理地设计程序逻辑、避免使用过多的同步代码块、避免嵌套锁等方法来预防死锁的发生。
此外,可以使用一些工具来帮助检测程序中潜在的死锁问题,并及时处理。
综上所述,如果在Java编程过程中遇到内存溢出或死锁问题,可以通过上述方法来解决,确保程序的稳定运行。
Java常见异常(RuntimeException)详细介绍并总结本⽂重在Java中异常机制的⼀些概念。
写本⽂的⽬的在于⽅便我很长时间后若是忘了这些东西可以通过这篇⽂章迅速回忆起来。
1. 异常机制1.1 异常机制是指当程序出现错误后,程序如何处理。
具体来说,异常机制提供了程序退出的安全通道。
当出现错误后,程序执⾏的流程发⽣改变,程序的控制权转移到异常处理器。
1.2 传统的处理异常的办法是,函数返回⼀个特殊的结果来表⽰出现异常(通常这个特殊结果是⼤家约定俗称的),调⽤该函数的程序负责检查并分析函数返回的结果。
这样做有如下的弊端:例如函数返回-1代表出现异常,但是如果函数确实要返回-1这个正确的值时就会出现混淆;可读性降低,将程序代码与处理异常的代码混爹在⼀起;由调⽤函数的程序来分析错误,这就要求客户程序员对库函数有很深的了解。
1.3 异常处理的流程1.3.1 遇到错误,⽅法⽴即结束,并不返回⼀个值;同时,抛出⼀个异常对象1.3.2 调⽤该⽅法的程序也不会继续执⾏下去,⽽是搜索⼀个可以处理该异常的异常处理器,并执⾏其中的代码2 异常的分类2.1 异常的分类2.1.1 异常的继承结构:基类为Throwable,Error和Exception继承Throwable,RuntimeException和IOException等继承Exception,具体的RuntimeException继承RuntimeException。
2.1.2 Error和RuntimeException及其⼦类成为未检查异常(unchecked),其它异常成为已检查异常(checked)。
2.2 每个类型的异常的特点2.2.1 Error体系 Error类体系描述了Java运⾏系统中的内部错误以及资源耗尽的情形。
应⽤程序不应该抛出这种类型的对象(⼀般是由虚拟机抛出)。
如果出现这种错误,除了尽⼒使程序安全退出外,在其他⽅⾯是⽆能为⼒的。
java中常见的NullPointerException异常下面列出了我们学习java时常出现的NullPointerException异常,以及它的解决办法1,空指针错误ng.NullPointerException 使用基本的JAVA数据类型,变量的值要么已经是默认值,如果没有对其正常赋值,程序便不能通过编译,因此使用基本的JAVA数据类型(double,float,boolean,char,int,long)一般不会引起空指针异常。
由此可见,空指针异常主要跟与对象的操作相关。
下面先列出了可能发生空指针异常的几种情况及相应解决方案:不管对象是否为空就直接开始使用。
(JSP)代码段1:out.println(request.getParameter("username"));描述:代码段1的功能十分简单,就是输出用户输入的表域"username"的值。
说明:看上去,上面的语句找不出什么语法错误,而且在大多数情况下也遇不到什么问题。
但是,如果某个用户在输入数据时并没有提供表单域"username"的值,或通过某种途径绕过表单直接输入时,此时request.getParameter("username")的值为空(不是空字符串,是空对象null。
),out对象的println方法是无法直接对空对象操作,因此代码段1所在的JSP页面将会抛出"ng.NullPointerException"异常。
即使对象可能为空时,也调用ng.Object或Object对象本身的一些方法如toString(), equals(Object obj)等操作。
(JSP)代码段2:String userName =request.getParameter("username");If (userName.equals("root")) {....}描述:代码段2的功能是检测用户提供的用户名,如果是用户名称为"root"的用户时,就执行一些特别的操作。
Java常见问题排查java问题的排查这么多年⼏乎没有什么改进,还是⽼的⽅法;每年查的问题也都很类似,不会有什么太多特殊的问题出现;java⼀些很常见的问题基本可以⽤⼀个模式去解的(⼤部分问题,只是有些问题⽐较复杂)所有的性能优化问题跟排查⼀个故障没有太⼤区别,因为最终都体现在⼀些系统指标上;查java问题要先知道系统的指标,因为所有的异常通常来讲系统指标都会有体现;⼀、排查java问题要先知道的1.系统指标查看1.1 top可以查看实时的每个核的状况1.2 tsvmstat好处是可以查看分钟级,不管是cpu、内存、⽹卡,可以查历史的每⼀分钟的各项指标,对历史问题⾮常有帮助,只是不能看每个核的运⾏状况;这两个是最重要的,所有的性能优化体现在系统上基本上都会体现在某个指标上;如果业务代码还可以,则会把某个硬件指标跑满,如果业务代码有问题,则硬件所有指标都没跑满,应⽤挂了。
2.要关注2.1 cpu2.1.1 us⼤多是应⽤本⾝的消耗java应⽤压⼒越⼤,我们追求的通常是us越⾼越好,这样说明主要消耗都在业务上,才说明业务代码写得还不错;2.1.2 sy 上下⽂切换和内核的消耗java应⽤的cpu的sy不应该太⾼,因为java应⽤主要是线程上下⽂的切换,内核层⾯会有⼀点消耗,但通常不多,如果sy很⾼的话,通常是因为⾼并发程序⼏个线程抢锁抢得⾮常厉害;2.1.3 iowait 磁盘除⾮是⽤java做存储相关,做业务层⾯⼀般不会碰到io问题;2.1.4 si 软中断,通常是⽹卡中断处理通常可以把si压到瓶颈是⽹卡的中断处理,就是⽹卡中断处理不过来,⽬前认为这种在硬件情况下⽆法突破,已经说明你的软件写得⾮常好;2.2 ⽹卡带宽cpu⼏乎可以展现所有的硬件状况,除了⽹卡带宽,⽤专⽤⼯具(tsvmstat)查看,通常不会把⽹卡跑满,除⾮有拉数据。
所以不管是做性能优化还是查问题之前,⼀定要看系统指标;⼆、java常见问题NoSuchMethodException、OutOfMemoryError、CPU us⾼、应⽤没响应、java进程没了有可能本地没碰到NoSuchMethodException,但线上碰到了,这个挺正常的;⼏乎所有java开发⼈员都会碰到OOM,不管是性能优化还是故障排查,通常我们的应⽤最后都会变成围绕CPU us去解决问题;1.NoSuchMethodException1.1 出现这种现象的原因1.1.1 java ClassLoader机制跟类加载有很⼤关系,它不是⼀个很好的机制,它有很多的问题,⽐如说启动完它会分⼏个⽬录分别加载jar包,这样就碰到jar版本冲突问题;1.1.2 java⾥让⼈极度头疼的jar版本冲突问题⼯程引⽤了A和B,A和B⼜都引⽤了C,但引⽤C的版本不同(groupId相同),这种问题maven就能解决,java⾥碰到的通常不是这种,这种编译就搞定了;通常碰到的是很多开源的框架很讨厌,他们的做法是依赖⼀个jar包时,把jar包⾥所有的代码拷贝到⾃⼰的代码⾥,然后打成他们⾃⼰的包,这种情况maven就不可能知道了,这种情况⼏乎所有的开源框架都⼲,这个是java⾥⾯很难解决的问题,因为冲突的问题很正常,⽽且有些根本不是你造成的,⼀旦出现就很容易出现NoSuchMethodException,就是有可能你⽤了⼀个新版本的⽅法,由于它加载了⽼的可能就会找不到,这种情况可能导致⽣产环境发布时发布的环境⼀模⼀样,有⼏台正常,有⼏台却发布失败,是因为java在加载⼀个⽬录下所有jar包的顺序完全取决于OS,⽽linux系统完全取决于inode的顺序,⽽inode的顺序不完全能控制;这个问题太⿇烦了,没⼈去解,理论上正确的解决⽅法是java加载jar包时是带加载⾃⼰的顺序去加载;有时候碰到很诡异的问题都是可以被解释的,也很正常;1.2 同类型的问题ClassNotFoundException/NoClassDefFoundError/ClassCastException1.3 排查⽅法1.3.1 -XX:+TraceClassLoading会打印出类是从哪个jar包加载的,如果有问题的话,就是那个位置不是你想的那个位置,需要修改配置并重启;1.3.2 jar -tvf *.jar如果对应⽤的运⾏机制很清楚,应⽤通常来讲都是tomcat或者jboss,意味着jar包都会从tomcat⾃⼰的rive下或者应⽤的web-inf⽬录下加载,如果你很清楚,你可以解压所有的jar,tvf不会展开只是⼀个列表⽽已,打印出所有的类,查看是否有同样包名同样类名的东西在两个jar包⾥都有,如果他们两个md5 sum出来不⼀样,则说明这两个版本冲突,冲突说明环境⼀直存在风险,全部都存在风险;版本冲突不会死⼈,最多就是⼀点点问题;碰到问题会解就好,通常就直接⽤jar -tvf *.jar看哪个class冲突了;这个时候就可以写个脚本⾃动的查看有没有两个类冲突的问题; 23561.4 解决⽅法1.4.1 mvn pom⾥去除不需要的版本provided;开源⼲的坏事那种只能作⼀个bugfix版本,只能这样;1.4.2 在打包阶段就尽可能避免掉版本冲突问题类加载相关的所有问题在java⾥都不算太难解,虽然不⼤难查问题,但解决起来稍微会有点复杂,就看问题有多⿇烦;2. ng.OutOfMemoryErrorOOM还包括了不报OOM,但GC已经⽐较频繁了这种现象,⽐如说应⽤写得还可以的情况下,压⼒施加上去,瓶颈会出现在gc,gc会⾮常的频繁,但它不会报OOM,jvm源码⾥只有以下七种原因可导致OOM,这七种在java⾥⾯多数都是有解决⽅案的,java⼯具体系⽐很多其他语⾔要成熟:GC overhead limitexceeded、Java Heap Space、Unable to create new native thread、PermGen Space、Direct buffer memory、Map failed、request {} bytes for {}. Out of space?2.1 GC overhead limit exceeded/Java Heap Space最常见的OOM后⾯跟的原因描述通常会是这两种2.1.1出现这两种现象的原因:java heap分配不出需要的内存了java heap(-Xms -Xmx)包括eden/survivor/survivor/OldGen;NewGen(-Xmn,-XX:SurvivorRatio)包括Eden、Survivor0、Survivor1,PermGen(-XX:PermSize,-XX:MaxPermSize)⼀个jvm内存分为java heap和c heap,7(含)以前perm gen还是在java heap中,7以后就移到c heap中了,⼤家更多接触的是java heap.-Xms -Xmx不允许设置成⼀样的值,否则会平⽩⽆故增加⾮常多的GC,⽐如说内存到了⼀定⼤⼩,它觉得不⼤够⽤了,还不到最⼤值,这个时候它会gc,把内存放⼤,它觉得要缩⼩了,也会gc,⽤来缩⼩;2.1.2 排查⽅法(确定不是因为heap size⼤⼩的情况下)既然java heap满了,我们就要知道这个堆被谁⽤掉,如果知道被谁⽤掉,这个问题理论上就可以被解决了,如果要知道堆被谁⽤掉,⾸先要拿到heap dump⽂件,否则谁也⽆法解决问题;这⾥说是oom不是cpu load⾼的问题;a.拿到HeapDump⽂件a.1 -XX:+HeapDumpOnOutOfMemoryError这个启动参数只会在第⼀次OOM时产⽣dump⽂件(⽂件名以.hprof结尾),在target或者⼯作⽬录下,后⾯再报OOM,就不会⽣成了,它认为已经⽣成了,所以有可能第⼀次dump的⽂件没⽤,要后⾯的才⾏,也就是抓不到现场;如果登陆机器时正在OOM(有些应⽤⼀直在OOM),可执⾏jmap -dumpa.2 jmap -dump:file=<⽂件名>,format=b [pid]如果正在执⾏gc,可执⾏此命令,执⾏时会强制执⾏⼀次Full GC(正是由于这个原因,不要在线上随便执⾏这个命令,FullGC耗时很多,可能导致线上应⽤挂掉),但有可能有时dump不出来,碰到了也很正常,那就不⽤强⾏dump了,没什么意思,这时可尝试⼀下⽤gcorea.3 gcore [pid]⽣成c版core dump,再运⾏jmap -dump从core dump提取出java的heap dump,jmap -dump:format=b,file=heap.hprof java路径 core.dump⽂件,最好的做法是⽤gcore,⽽不是jmap -dump,gcore特别快,jmap特别慢,因为jmap -dump除了会引发FullGC也会⽣成⼀个与java heap 同⼤⼩的⽂件,java heap 有8g,⽣成的⽂件就有8g,java heap有100g时OOM就别查了,因为它会⽣成⼀个100g的⽂件,这是java排查问题⼀个致使的弱点,⽬前为⽌,业界也没有很好的解决⽅案;多数OOM的问题重启(绝对⼤招)是可以解决的,只是重启问题在于哪天⼜会出现。
浅析Java异常处理机制及应用摘要:Java异常处理机制是Java编程语言中最为重要的机制之一,它可以在代码中处理各种类型的异常。
本文将对Java异常处理机制进行浅析,并从应用层面探讨一些常见的Java异常处理方法。
关键词:Java,异常处理,应用正文:一、Java异常处理机制Java异常处理机制是Java编程语言中最为重要的机制之一。
在Java语言中,异常是指一个程序运行时产生的意外情况,可以是代码中的错误,也可以是由于外部环境因素导致的错误。
Java提供了一整套异常处理机制,可以帮助开发者处理各种类型的异常。
在Java中,异常通常被定义为继承自Throwable类的任意一个子类。
常见的异常类型包括RuntimeException、IOException、ClassNotFoundException、ArithmeticException等等。
Java中异常的处理主要分为两种方式:try-catch块和throws语句。
try-catch块是一种捕捉异常的方法,其基本语法结构如下:```try {// 可能会抛出异常的代码块} catch (type1 e1) {// 处理type1类型异常的代码块} catch (type2 e2) {// 处理type2类型异常的代码块} finally {// 不管是否发生异常,都会执行的代码块}```throws语句是一种抛出异常的方法,其基本语法结构如下:```public void methodName() throws ExceptionType {// 可能会抛出异常的代码块}```二、Java异常处理的应用Java异常处理机制应用广泛,以下是应用层面探讨一些常见的Java异常处理方法。
1、基于try-catch块的异常处理try-catch块是Java中最基本的异常处理方法。
它可以在程序运行时捕捉异常,并且根据不同的异常类型采取不同的处理方法。
ng.NullPointerException原因是:有空指针,有地址没赋值2.Exception in thread "main" ng.ArithmeticException: / by zero原因是除数是03.ArrayIndexOutOfBoundsException原因是:数组越界ng.NumberFormatException原因是:数字格式化有问题5.Unhandled exception type Exception原因是:没有进行异常处理6.进行国际化操作的时候遇到这样的错误:Exception in thread "main" java.util.MissingResourceException: Can't find bundle for base name Message, locale zh_CN答:因为在命令提示符中,是没有错误的解决方法是:在myeclipse中,会出现这个错误java国际化之Can't find bundle for base name1.初步学习最近在学习ResourseBundle时遇到了“Can't find bundle for base name ”这个错误搞了很久才解决了。
原因就是类路径问题要将属性文件放在类路径中!百度里很多都是教程但没有涉及到解决方法!2.中文显示:测试文件java 代码package com.lht.ResourseBundleStudy;import java.util.ResourceBundle;public class ResourseBundleDemo {public static void main(String[] args) {ResourceBundle resource = ResourceBundle.getBundle("test");System.out.print(resource.getString("msg0") + "!");System.out.println(resource.getString("msg1") + "!"); }}test.propertiesmsg0="Hello World"msg1="da jia hao"开始自己测试的时候:将属性文件放在bin/下也试过也不行无赖中就在google中搜索了一下终于在sun的java论坛(/thread.jspa?threadID=660477&messageID=4231534)中找到了线索下面是帖子的内容:I've solved the problem the best way possible. Basically what i've done is added a new class folder named config to the project home dir. Then i added this classfolder to the classpath in project properties. After doing all of this you only need to reference the properties file by "Email".Hope this helps anyone else who is having similiar problems.基本意思就是在src下建立classes(名字无所谓)文件夹将属性文件存放在下面,然后将这个文件夹加入类路径中!运行就可以了:加入类路径的方法:你的工程文件夹->properties->选择Libraries选项卡->Add Class Folder 将刚才建立的文件夹加入就可以了!结果如下:"Hello World"!"da jia hao";!2.中文显示在classes目录下建立message_CH.properties内容如下:ms0="大家好"同样用上面的测试文件!结果如下:"?ó????"!乱码怎么回事啊!在百度里搜索后找到了答案有以为网友写的很清楚:/3885062.html 下面引用如下:原理Property文件中,使用的编码方式根据机器本身的设置可能是GBK或者UTF-8。
Java内存溢出(OOM)异常完全指南本⽂分析什么情况会导致这些异常出现,提供⽰例代码的同时为您提供解决指南。
Nikita Salnikov-TarnovskiPlumbr Co-Founder and VP of Engineering本⽂内容来源于,对原⽂内容有删减和补充这也许是⽬前最为完整的Java OOM异常的解决指南。
1、ng.OutOfMemoryError:Java heap spaceJava应⽤程序在启动时会指定所需要的内存⼤⼩,它被分割成两个不同的区域:Heap space(堆空间)和Permgen(永久代):JVM内存模型⽰意图这两个区域的⼤⼩可以在JVM(Java虚拟机)启动时通过参数-Xmx和-XX:MaxPermSize设置,如果你没有显式设置,则将使⽤特定平台的默认值。
当应⽤程序试图向堆空间添加更多的数据,但堆却没有⾜够的空间来容纳这些数据时,将会触发ng.OutOfMemoryError: Java heap space异常。
需要注意的是:即使有⾜够的物理内存可⽤,只要达到堆空间设置的⼤⼩限制,此异常仍然会被触发。
原因分析触发ng.OutOfMemoryError: Java heap space最常见的原因就是应⽤程序需要的堆空间是XXL号的,但是JVM提供的却是S号。
解决⽅法也很简单,提供更⼤的堆空间即可。
除了前⾯的因素还有更复杂的成因:流量/数据量峰值:应⽤程序在设计之初均有⽤户量和数据量的限制,某⼀时刻,当⽤户数量或数据量突然达到⼀个峰值,并且这个峰值已经超过了设计之初预期的阈值,那么以前正常的功能将会停⽌,并触发ng.OutOfMemoryError: Java heap space异常。
内存泄漏:特定的编程错误会导致你的应⽤程序不停的消耗更多的内存,每次使⽤有内存泄漏风险的功能就会留下⼀些不能被回收的对象到堆空间中,随着时间的推移,泄漏的对象会消耗所有的堆空间,最终触发ng.OutOfMemoryError: Java heap space错误。
JAVA常见异常1. ng.nullpointerexception这个异常大家肯定都经常遇到,异常的解释是"程序遇上了空指针",简单地说就是调用了未经初始化的对象或者是不存在的对象,这个错误经常出现在创建图片,调用数组这些操作中,比如图片未经初始化,或者图片创建时的路径错误等等。
对数组操作中出现空指针,很多情况下是一些刚开始学习编程的朋友常犯的错误,即把数组的初始化和数组元素的初始化混淆起来了。
数组的初始化是对数组分配需要的空间,而初始化后的数组,其中的元素并没有实例化,依然是空的,所以还需要对每个元素都进行初始化(如果要调用的话)2. ng.classnotfoundexception这个异常是很多原本在jb等开发环境中开发的程序员,把jb下的程序包放在wtk下编译经常出现的问题,异常的解释是"指定的类不存在",这里主要考虑一下类的名称和路径是否正确即可,如果是在jb下做的程序包,一般都是默认加上package的,所以转到wtk下后要注意把package的路径加上。
3. ng.arithmeticexception这个异常的解释是"数学运算异常",比如程序中出现了除以零这样的运算就会出这样的异常,对这种异常,大家就要好好检查一下自己程序中涉及到数学运算的地方,公式是不是有不妥了。
4. ng.arrayindexoutofboundsexception这个异常相信很多朋友也经常遇到过,异常的解释是"数组下标越界",现在程序中大多都有对数组的操作,因此在调用数组的时候一定要认真检查,看自己调用的下标是不是超出了数组的范围,一般来说,显示(即直接用常数当下标)调用不太容易出这样的错,但隐式(即用变量表示下标)调用就经常出错了,还有一种情况,是程序中定义的数组的长度是通过某些特定方法决定的,不是事先声明的,这个时候,最好先查看一下数组的length,以免出现这个异常。
Java Web开发中的常见问题汇总与解决方案Java Web开发是现在互联网行业中非常热门的技术方向之一,它的发展势头也是越来越迅猛。
然而,在开发Java Web应用程序的过程中,总会遇到各种各样的问题,有的是因为技术不够熟练导致的,有的是由于环境不同而产生的。
为了让大家更好地掌握Java Web开发,本文将为您汇总整理了一些Java Web开发中常见的问题,并提供相应的解决方案。
一、数据访问异常在Java Web开发中,我们经常会遇到与数据库相关的异常。
尤其是在开发大型系统时,访问数据库的错误可能会成倍地影响系统的性能和可靠性。
以下列举一些常见的数据访问异常和解决方案。
1、连接池过期连接池过期是一个非常常见的问题,尤其是在系统高并发的情况下,会造成系统性能的明显下降。
解决方法是通过合理的配置和优化连接池的使用,提高系统的吞吐量和稳定性。
2、防止数据库死锁死锁是在高并发系统中经常遇到的问题之一。
如果多个线程并发访问数据库的同一个资源,就有可能导致死锁的产生。
要解决这个问题,可以通过使用数据库的锁机制来避免死锁的产生。
3、被动连接关闭一些数据库和Java ORM框架对于空闲连接资源的回收策略不同,可能会导致被动关闭连接的情况发生。
解决方案是做好连接池的配置和优化,避免过度的空闲连接资源占用。
二、Web服务器异常Java Web开发中的Web服务器异常也是非常常见的问题。
以下列举一些常见的Web服务器异常和解决方案。
1、多线程并发处理异常在高并发的情况下,Web服务器可能会产生并发处理异常,这种情况下就需要通过合理的代码设计和服务器配置来保证系统的性能和稳定性。
2、内存溢出和内存泄漏内存溢出和内存泄漏是很多Java Web开发者常常碰到的问题。
要解决这个问题,可以通过调整JVM内存参数,优化代码的编写和设计,避免无意中创建了对象并长时间占用内存资源。
3、负载均衡异常Java Web应用程序在高并发的情况下,可能会导致负载均衡的异常。
Java编程中常见错误排查及调试技巧在Java编程过程中,由于代码的复杂性和开发环境的多样性,常常会遇到各种错误和问题。
良好的排查和调试技巧是解决这些问题的关键所在。
本文将介绍一些常见的错误排查和调试技巧,帮助开发人员更高效地修复Java程序中的错误。
一、错误排查技巧1. 查看错误信息在程序运行过程中,如果发生了错误,Java会提供相应的错误信息。
在调试时,首先要仔细阅读错误信息,并理解错误的原因和位置。
错误信息通常会包含错误的类型、堆栈跟踪和可能的原因。
通过仔细分析错误信息,可以定位到错误所在的具体代码行,从而更有针对性地解决问题。
2. 使用日志日志是排查错误的重要工具之一。
在代码中添加适当的日志语句,可以帮助开发人员了解程序的执行情况。
通过查看日志,可以追踪代码执行过程中的变量值、方法调用等重要信息,从而更好地定位错误。
常用的Java日志框架包括Log4j、Logback等,可以方便地记录、输出和管理日志。
3. 利用断言断言是一种方便的调试工具。
通过在代码中插入断言语句,可以对程序的预期结果进行验证,如果条件不符合预期,则会抛出AssertionError异常。
断言可以用于验证前置条件、方法返回值等,在调试过程中可以帮助开发人员发现错误和问题。
4. 调试工具Java提供了强大的调试工具来辅助排查错误。
例如,可以使用Java自带的调试器(如Eclipse中的调试功能),设置断点并逐步执行代码,观察变量值的变化,从而找出错误的原因。
此外,还可以使用一些第三方调试工具,如VisualVM、JConsole等,来监控程序的运行状态和性能指标,以帮助排查问题。
5. 编写单元测试编写单元测试是预防和排查错误的重要手段。
通过编写全面、有效的单元测试,可以快速发现代码中的问题,并验证修复后代码的正确性。
单元测试应该覆盖边界情况、异常情况等各种可能的情况,以保证代码的稳定性和健壮性。
二、调试技巧1. 使用日志除了在错误排查时使用日志外,日志在调试过程中同样有重要作用。
软件开发中最常见的24种错误类型及其解决方案在软件开发中,无论是新手还是经验丰富的开发人员,都难免会遇到各种各样的错误和挑战。
这些错误可能来自不同的层面,比如编码、测试、部署和维护等。
为了帮助开发人员更好地解决这些问题,本文总结了软件开发中最常见的24种错误类型,并提供了相应的解决方案。
1. 死锁错误死锁是一种多线程执行过程中常见的错误类型。
当多个线程都在等待某个资源的时候,就有可能出现死锁。
这种错误通常会导致程序停止响应,无法正常执行。
解决方案:通过合理规划线程代码顺序,减少出现死锁的概率。
对于已经出现死锁的情况,可以通过进程管理工具来手动结束进程。
2. 内存泄漏错误内存泄漏是指程序在运行时分配的内存空间没有被释放,导致程序在长时间运行后出现崩溃或者异常。
这种错误通常会难以定位,因为它不会立即导致程序崩溃。
解决方案:通过代码审查和内存泄漏检测工具找出问题代码,并在代码中添加适当的释放内存的语句。
3. 缓存不一致错误在分布式系统中,缓存是一种常见的技术,用于提高系统性能。
然而,由于缓存的更新机制存在一定的滞后性,当多个系统同时访问某个缓存时,就容易出现缓存不一致的情况,导致数据不准确或者出现异常。
解决方案:利用分布式缓存系统或者锁机制,实现缓存的同步更新,避免不一致的情况。
4. 空指针错误空指针错误是指程序中使用了空指针变量,导致程序崩溃或者出现异常。
这种错误通常由于变量没有被初始化或者被误删除导致。
解决方案:在程序中对变量进行合适的初始化,并添加空指针判断,确保变量不是空指针。
5. 栈溢出错误栈溢出是指程序在执行中使用了过多的栈空间,导致程序崩溃或者异常。
这种错误通常由于递归调用、过深的函数调用链等因素引起。
解决方案:对程序进行优化和重构,减少递归调用的次数和深度,并分离长函数实现。
6. 逻辑错误逻辑错误是指程序在实现业务逻辑时出现的错误,导致程序无法正确执行。
这种错误通常由于实现逻辑不完整或者存在逻辑漏洞引起。
Java开发中的常见错误及其解决方案Java是一种跨平台、面向对象、高性能的编程语言,广泛用于Web应用程序开发、移动应用程序开发、游戏开发等方面。
然而,在开发Java应用程序的过程中,常常会出现一些错误和问题,这些问题可能是语法错误、逻辑错误、性能问题等等。
本文将讨论Java开发中的一些常见问题及其解决方案,帮助开发者更好地理解和应对这些问题。
1. 内存泄露内存泄露是一种常见的Java错误。
它指的是程序不必要地占用了内存,但却没有释放。
当一个程序不断运行时,这些未释放的内存会积累,最终导致程序崩溃或变慢。
解决方案:追踪内存泄露的原因并修复它。
可以使用诸如Eclipse Memory Analyzer(MAT)等工具来分析程序内存,找出内存泄漏的原因。
修复内存泄漏通常涉及检查代码中的对象生命周期、确保适当释放资源等。
2. 空指针异常空指针异常是Java程序员最常遇到的问题之一。
它通常是由于访问一个空对象引用而导致的。
这种错误很容易发生,因为程序员可能忘记了为某些对象赋值或在不为空的情况下使用这些对象。
解决方案:添加有效的空对象检查。
程序员应该在使用对象之前检查其是否为空,以避免空指针异常。
可以使用条件语句或对象的非空检查运算符来实现这一点。
3. 类型转换异常类型转换异常通常发生在试图将一个类型转换为不兼容的另一个类型时。
例如,将字符串转换为数字时,如果字符串不是数字,则会发生类型转换异常。
解决方案:使用合适的类型转换方法。
程序员应该使用适当的类型转换方法,例如parseInt方法将字符串转换为整数,以避免类型转换异常。
此外,程序员应该检查数据类型是否兼容,避免尝试将不兼容的数据类型进行转换。
4. 并发问题并发问题是在多个线程同时访问共享数据时发生的问题。
这种情况可能导致数据不一致、死锁、竞争条件等问题。
在Java开发中,常见的并发问题包括线程安全性、死锁、条件竞争等。
解决方案:使用同步措施。
同步措施是指在多个线程中访问共享数据时保持数据一致性的方法。
Java⾥的异常(Exception)详解作为⼀位初学者, 本屌也没有能⼒对异常谈得很深⼊. 只不过⾥关于Exception的东西实在是很多. 所以这篇⽂章很长就是了..⼀, 什么是java⾥的异常由于java是c\c++ 发展⽽来的, ⾸先我们先看看c语⾔⾥的错误.1.1 c语⾔⾥的错误我们实现1个程序的过程包括, 代码编写, 编译代码成为程序, 执⾏程序..其中⼤部分常见的语法错误都会被编译代码这样部过滤掉. 但是即使通过了编译. 执⾏程序这⼀步可能还是会有错误.原因很多, 例如常见的除数为0, 内存溢出(数组的index超出界限), 或者内存被其他程序修改等.最简单的例⼦:[java]1. #include <stdio.h>2.3. int f(int a, int b){4. return a/b;5. }6.7. int main(){8. int i = f(8,0);9. printf("i is %d\n",i);10. return 0;11. }上⾯的例⼦编译时是⽆错的, 但是⼀旦执⾏就会提⽰吐核错误了.c语⾔⾥对这种执⾏时出现的错误是⽆能为⼒的, ⼀旦出错就会整个程序崩溃, 就不会在继续执⾏下⾯的代码.⽽且很多时候出错信息很少, 让你⽆法判断出错的原因和地⽅, 只能⼀步步⼩⼼debug...所以很多⽤c写的程序有时会出现⾮法关闭的现象.解决⽅法只能是在代码⾥对可能出错的地⽅添加if 判断.例如f()函数⾥可以对b进⾏判断, 如果是0就不执⾏.1.2 java⾥运⾏时出现的错误java⾥编译器对代码的规范性⽐c严格得多. 但是即使如此, 通过编译的java程序有时也很难避免执⾏时出错.例如, 将上⾯的c程序改编成java程序:[java]1. package Exception_kng;2.3. class Exp1{4. public int f(int a, int b){5. return a/b;6. }7. }8.9. public class Expt_1{10. public static void g(){11. Exp1 e = new Exp1();12. int i = e.f(8,0);13. System.out.printf("i is %d\n", i);14. }15. }运⾏时⼀样会出错, 下⾯是出错信息:[java]1. [java] Caused by: ng.ArithmeticException: / by zero2. [java] at Exception_kng.Exp1.f(Expt_1.java:5)3. [java] at Exception_kng.Expt_1.g(Expt_1.java:12)4. [java] at Enter_1.main(Enter_1.java:31)但是可以见到, java告诉你出错的类型: 运算错误(ArithmeticExcetion), 出错信息和出错的类与⽂件⾏数输出, ⽅便你调试. jvm虚拟机是会对错误作出⼀定的处理的.所以可以简单地将java⾥的异常理解成java运⾏时出现的错误, 异常机制就是对这种错误进⾏处理的机制.1.3 java异常的定义实际上, 当java程序执⾏时出现错误时, jvm会把执⾏时出错的信息(例如出错原因, 类型, 位置) 收集,然后打包成为1个对象(object), 程序员可以对这种对象进⾏处理. 这种对象就是所谓的异常.可能出现的异常的代码并不是肯定会出现异常, 取决于执⾏环境和数据.!⼆, java⾥的异常的分类.见下图:Throwable/ \Error Exception/ / \xxxxxx xxxxxx RuntimeException/ \xxxxxx ArithmeticException上图的所有对象都是类.Throwable 代表是可抛出的.Error 代表的是严重错误, 这种错误程序员⽆法进⾏处理, 例如操作系统崩溃, jvm出错, 动态链接库失败等. Error并不是异常, 不是本⽂的重点.Exception 代表的就是异常了. 它下⾯很多派⽣类, 其中它的派⽣类也分两种, ⼀种是RuntimeException(运⾏时异常), 其他的都是⾮运⾏时异常RuntimeException 包括除数为0, 数组下标超界等. 运⾏时异常的派⽣类有很多, 其产⽣频率较⾼. 它的派⽣类可以由程序处理或者抛给(throw) 给jvm处理. 例如上⾯的例⼦就是抛给了jvm处理, jvm把程序中断执⾏, 并把错误信息输出到终端上.⾮RuntimeExcption 这种异常属于Excepion的派⽣类(上⾯红⾊的xxx), 但是不是RuntimeException的派⽣类, 这种异常必须由程序员⼿动处理,否则不通过编译.ArithmeticExcpetion 算术异常, 它是RuntimeException的派⽣类, 所以程序员不⼿动处理也通过编译, 只不过出错时会被jvm处理.三, java⾥对异常的处理java⾥对异常的处理有三种.3.1 程序猿对有可能出现的异常使⽤try catch处理.例如我们将上⾯的例⼦改动⼀下:[java]1. package Exception_kng;2.3. class Exp2{4. public int f(int a, int b){5. int i = 0;6. try{7. i = a/b;8. }9. catch(Exception e){10. System.out.printf("Exception occurs!!\n");11. System.out.println(e.getMessage()); //print the root cause12. System.out.printf("===========================\n");13. e.printStackTrace(); //print the info of function stuck.14. }15.16. return i;17. }18. }19.20. public class Expt_2{21. public static void g(){22. Exp2 ex = new Exp2();23. int i = ex.f(8,0); //call f()24. System.out.printf("i is %d\n", i); //successfully executed25. }26. }在f()函数中对可能出现的异常的代码进⾏try catch处理后, 程序会执⾏catch⾥的代码. ⽽且不会中断整个程序, 继续执⾏try catch后⾯的代码.程序执⾏输出:[java]1. [java] Exception occurs!!2. [java] / by zero3. [java] ===========================4. [java] ng.ArithmeticException: / by zero5. [java] at Exception_kng.Exp2.f(Expt_2.java:7)6. [java] at Exception_kng.Expt_2.g(Expt_2.java:23)7. [java] at Enter_1.main(Enter_1.java:31)8. [java] i is 0注意最终也执⾏了g()函数中的最后⼀条语句, 输出了i的值.也就是说try catch处理后并不会终⽌程序, 令程序即使出现了错误, 也可以对错误进⾏⼀定的处理后继续执⾏. 这就是java异常机制⽐c语⾔安全的地⽅.下⾯会详细讲解 try catch.注:getMessage() ⽅法: Exception类的⽅法之⼀, 返回异常的原因, 上⾯的 / by zero 就是这个⽅法输出的.printStackTrace(): Exception类的⽅法之⼀, 在屏幕输出函数栈信息, 也就是异常出现的地⽅.3.2 函数⾥并不处理异常, 使⽤throw or throws 关键字把可能出现的异常抛给调⽤该函数的上级函数处理.例如我在f()函数中不想处理可能出现的异常, 想把它抛出上级函数处理:下⾯是个例⼦:[java]1. package Exception_kng;2.3. class Exp3{4. public int f(int a, int b){5. if (0 == b){6. throw new ArithmeticException("Shit !!! / by zero!");7.8. }9.10. return a/b;11. }12. }13.14. public class Expt_3{15. public static void g() throws ArithmeticException{16. Exp3 ex = new Exp3();17. int i = 22;18. i = ex.f(8,0); //throw excetpion19. System.out.printf("i is %d\n", i); //failed executed20. System.out.printf("g() is done!!\n"); //failed executed21. }22.23. public static void h(){24. try{25. g();26. }catch(ArithmeticException e){27. System.out.printf("Exception occurs!!\n");28. System.out.println(e.getMessage()); //print the root cause29. System.out.printf("===========================\n");30. e.printStackTrace(); //print the info of function stuck.31. }32.33. System.out.printf("h() is done!!\n"); //successfully executed34. }35. }可以见到f() 加了个条件判断, 如果参数b = 0, 使⽤throw 直接⼿动抛出1个异常. 让调⽤它的函数处理.g()调⽤f()函数, 预见到f()可能有异常, 但是也不想处理, 使⽤throws 关键字告诉调⽤它的函数本函数有可能抛出这种异常. // 注, 这⾥的throws 对程序并没有实质的影响.h()调⽤g(), 简单g()定义的throws, ⽤try catch在本函数进⾏处理.输出:[java]1. [java] Exception occurs!!2. [java] Shit !!! / by zero!3. [java] ===========================4. [java] ng.ArithmeticException: Shit !!! / by zero!5. [java] at Exception_kng.Exp3.f(Expt_3.java:6)6. [java] at Exception_kng.Expt_3.g(Expt_3.java:18)7. [java] at Exception_kng.Expt_3.h(Expt_3.java:25)8. [java] at Enter_1.main(Enter_1.java:31)9. [java] h() is done!!注意这个程序没有执⾏g() 最后的代码.throw 和 throws 后⾯也会详细讲解.3.3 交给jvm虚拟机处理假如上⾯的例⼦h() 也不处理怎么办? 就如1.2 的例⼦, 会抛给jvm处理.但是这种情况只适⽤于RuntimeExecption及其派⽣类.jvm怎么处理呢, 就是中断整个程序, 并把异常信息输出到屏幕上.实际上, 当java程序的1个函数抛出异常时,⾸先会检查当前函数有没有try catch处理, 如果⽆检查上⼀级函数有⽆try..catch处理....这样在函数栈⾥⼀级⼀级向上检查, 如果直⾄main函数都⽆try..catch, 则抛给jvm..项⽬中强烈建议尽量⼿动处理, 不要把异常交给jvm.四,Try catch finally 的处理机制.这⾥开始详解try catch finally了.语法是这样的.try{可能出异常的若⼲⾏代码;}catch(ExceptionName1 e){产⽣ExceptionName 1的处理代码;}catch(ExceptionName2 e){产⽣ExceptionName 2的处理代码;}...finally{⽆论如何, 最终肯定会执⾏的代码}4.1 try catch finally的执⾏路线.下⾯⽤个例⼦来说明:[java]1. try{2. f();3. ff();4. }5. catch(ArithmeticException e){6. g();7. }8. catch(IOException e){9. gg();10. }11. catch(AuthorizedException e){12. ggg();13. }14. finally{15. h();16. }17.18. k();4.1.1 当try⾥⾯的f()抛出了IOException当f()抛出了异常, 那么ff()就不会执⾏了. 程序会尝试捕捉异常.⾸先捕捉ArithmeticException, 捕捉失败.接下来捕捉IOException, 捕捉成功, 执⾏gg();⼀旦捕捉到⼀个异常, 不会再尝试捕捉其他异常, 直接执⾏finally⾥的h();执⾏后⾯的函数k().也就是说路线是:f() -> gg() -> h() -> k()有2点要注意的.1. f()函数极有可能未完整执⾏, 因为它抛出了异常, 抛出异常的语句执⾏失败, 之后的语句放弃执⾏.2. try{} ⾥⾯, f()之后的语句, 例如ff()放弃执⾏.4.1.2 没有任何异常抛出这种情况很简单, 就是try{}⾥⾯的代码被完整执⾏, 因为没有抛出任何异常, 就不会尝试执⾏catch⾥的部分, 直接到finally部分了.路线是:f() -> ff() -> h() -> k()4.2 如何确定要捕捉的异常名字.也许有⼈会问, 我们怎么知道到底会抛出什么异常?下⾯有3个解决⽅案.1.看代码凭经验, 例如看到1段除法的代码, 则有可能抛出算术异常.2.在catch的括号⾥写上Exception e, 毕竟Exception 是所有其他异常的超类, 这⾥涉及多态的知识, ⾄于什么是多态可以看看本⼈的另⼀篇⽂章.3. 观察被调⽤函数的函数定义, 如果有throws后缀, 则可以尝试捕捉throws 后缀抛出的异常4.3 为什么需要finally包括我在内很多⼈会觉得finally语句简直多勾余, 既然是否捕捉到异常都会执⾏, 上⾯那个例⼦⾥的h()为什么不跟下⾯的k() 写在⼀起呢.上⾯的例⼦的确看不出区别.但下⾯两种情况下就体现了finally独特的重要性.4.3.1 抛出了1个异常, 但是没有被任何catch⼦句捕捉成功.例如try⾥⾯抛出了1个A异常, 但是只有后⾯只有捕捉B异常, 和C异常的⼦句.这种情况下, 程序直接执⾏finally{}⾥的⼦句, 然后中断当前函数, 把异常抛给上⼀级函数, 所以当前函数finally后⾯的语句不会被执⾏.例⼦:[java]1. package Exception_kng;2.3. import .*;4. import java.io.*;5.6. class Exp4{7. public int f(int a, int b) throws IOException, BindException{8. return a/b;9. }10. }11.12. public class Expt_4{13. public static void g(){14. Exp4 ex = new Exp4();15. int i = 22;16. try{17. System.out.printf("g() : try!!\n"); //failed18. i = ex.f(8,0); //call f()19. }20. catch(BindException e){21. System.out.printf("g() : BindException!!\n"); //failed22. }23. catch(IOException e){24. System.out.printf("g() : IOException!!\n"); //failed25. }26. finally{27. System.out.printf("g() : finaly!!\n"); //successfully executed28. }29. System.out.printf("g() is done!!\n"); //failed30. }31.32. public static void h(){33. try{34. g();35. }catch(ArithmeticException e){36. System.out.printf("Exception occurs!!\n");37. System.out.println(e.getMessage()); //print the root cause38. System.out.printf("===========================\n");39. e.printStackTrace(); //print the info of function stuck.40. }41.42. System.out.printf("h() is done!!\n"); //successfully executed43. }44. }我所说的情况, 就在上⾯例⼦⾥的g()函数, g()函数⾥尝试捕捉两个异常, 但是抛出了第3个异常(ArithmeticException 算术异常).所以这个异常会中断g()的执⾏, 因为没有被捕捉到, 然后抛给调⽤g()的 h()函数处理, ⽽在h()捕捉到了, 所以h()函数是能完整执⾏的.也就是说g()⾥的[java]1. System.out.printf("g() is done!!\n"); //failed执⾏失败⽽h()⾥的[java]1. System.out.printf("h() is done!!\n"); //successfully executed执⾏成功但是⽆论如何, g()⾥的finally{}部分还是被执⾏了执⾏结果如下:[java]1. [java] g() : try!!2. [java] g() : finaly!!3. [java] Exception occurs!!4. [java] / by zero5. [java] ===========================6. [java] ng.ArithmeticException: / by zero7. [java] at Exception_kng.Exp4.f(Expt_4.java:8)8. [java] at Exception_kng.Expt_4.g(Expt_4.java:18)9. [java] at Exception_kng.Expt_4.h(Expt_4.java:34)10. [java] at Enter_1.main(Enter_1.java:31)11. [java] h() is done!!这种情况是1中编程的低级错误, 在项⽬中是不允许出现.避免⽅法也⼗分简单, 在catch⼦句集的最后增加1个catch(Exception e)就ok, 因为Exception是所有异常的超类, 只要有异常抛出, 则肯定会捕捉到.4.3.2 在catch⼦句内有return⼦句.下⾯例⼦:[java]1. try{2. f();3. ff();4. }5. catch(ArithException e){6. g();7. return j();8. }9. catch(IOException e){10. gg();11. return j();12. }13. catch(AuthorizedException e){14. ggg();15. return j();16. }17. finally{18. h();19. }20.21. k();假如在f()函数抛出了IOExcepion 异常被捕捉到.那么执⾏路线就是f() -> gg() -> j() -> h() -> 上⼀级function也就说, 这种情况下finally⾥的⼦句会在return回上⼀级function前执⾏. ⽽后⾯的k()就被放弃了.4.3.3 finally作⽤⼩结.可以看出, finally⾥的语句, ⽆论如何都会被执⾏.⾄有两种情况除外, ⼀是断电, ⼆是exit函数.在项⽬中, 我们⼀般在finally编写⼀些释放资源的动作, 例如初始化公共变量. 关闭connections, 关闭⽂件等.4.4 try catch finally⾥⼀些要注意的问题.4.4.1 ⽆论如何最多只有1个catch被执⾏这个上⾯提到过了, ⼀旦捕捉到1个异常, 就不会尝试捕捉其他异常.如果try⾥⾯的⼀段代码可能抛出3种异常A B C,⾸先看它先抛出哪个异常, 如果先抛出A, 如果捕捉到A, 那么就执⾏catch(A)⾥的代码. 然后finally.. B和C就没有机会再抛出了.如果捕捉不到A, 就执⾏finally{}⾥的语句后中断当前函数, 抛给上⼀级函数...(应该避免)4.4.2 有可能所有catch都没有被执⾏两种情况, 1就是没有异常抛出, 另⼀种就是抛出了异常但是没有捕捉不到(应该避免)4.4.3 先捕捉⼦类异常, 再捕捉⽗类异常, 否则编译失败加⼊try ⾥⾯尝试捕捉两个异常, 1个是A, 1个是B, 但是A是B的⽗类.这种情况下, 应该把catch(B)写在catch(A)前⾯.原因也很简单, 加⼊把catch(A)写在前⾯, 因为多态的存在, 即使抛出了B异常, 也会被catch(A)捕捉, 后⾯的catch(B)就没有意义了.也就是说如果捕捉Exception这个异常基类, 应该放在最后的catch⾥, 项⽬中也强烈建议这么做, 可以避免上述4.3.1的情况出现.4.4.4 catch与catch之间不能有任何代码.这个没什么好说的. 语法规则4.4.5 finally⾥不能访问catch⾥捕捉的异常对象e每1个异常对象只能由catch它的catch⼦句⾥访问.4.4.6 try⾥⾯的定义变量不能在try外⾯使⽤.跟if类似, 不多说了.4.4.7 try catch finally可以嵌套使⽤.这个也不难理解..五, throw 和throws的机制和⽤法.下⾯开始详讲异常另⼀种处理⽅法throw 和 throws了.注意的是, 这两种⽤法都没有真正的处理异常, 真正处理的异常⽅法只有try catch, 这两种⽅法只是交给上⼀级⽅法处理.就如⼀个组织⾥ , 有1个⼤佬, 1个党主, 1个⼩弟.⼤佬叫党主⼲活, 堂主叫⼩弟⼲活, 然后⼩弟碰上⿇烦了, 但是⼩弟不会处理这个⿇烦, 只能中断⼯作抛给党主处理, 然后堂主发现这个⿇烦只有⼤佬能处理, 然后抛给⼤佬处理..道理是相通的..5.1 throw 的语法与作⽤throws的语法很简单.语法:throw new XException();其中xException必须是Exception的派⽣类.这⾥注意throw 出的是1个异常对象, 所以new不能省略作⽤就是⼿动令程序抛出1个异常对象.5.2 throw 1个 RuntimeException及其派⽣类我们看回上⾯3.2 的例⼦:[java]1. public int f(int a, int b){2. if (0 == b){3. throw new ArithmeticException("Shit !!! / by zero!");4.5. }6.7. return a/b;8. }5.2.1 throw会中断当前函数, 当前函数执⾏失败(不完整)当这个函数的if 判断了b=0时, 就利⽤throws⼿动抛出了1个异常. 这个异常会中断这个函数. 也就是说f()执⾏不完整, 是没有返回值的.5.2.2, 接下来哪个调⽤这个函数就会在调⽤这个函数的语句上收到异常.[java]1. public void g(){2. int i;3. h();4. i = f(); //recevie excepton5. k();6. }例如上没的g()函数, 在调⽤f() 会收到1个异常.这时g()函数有三种选择.1. 不做任何处理这时, g()收到f()⾥抛出的异常就会打断g()执⾏, 也就是说g()⾥⾯的k(); 被放弃了, 然后程序会继续把这个函数抛给调⽤g()函数.然后⼀级⼀级寻求处理, 如果都不处理, 则抛给jvm处理. jvm会中断程序, 输出异常信息. 这个上没提到过了.2. 使⽤try catch处理如果catch成功, 则g()函数能完整执⾏, ⽽且这个异常不会继续向上抛.如果catch失败(尽量避免), 则跟情况1相同.5.3 throw 1个⾮RuntimeException派⽣类的异常将上⾯的例⼦改⼀下:[java]1. public int f(int a, int b){2. if (0 == b){3. throw new IOException("Shit !!! / by zero!");4. }5.6. return a/b;7. }例如, 我不想抛出ArithmeticException, 我想抛出IOExcetpion.注意这⾥, IOException虽然逻辑上是错误的(完全不是IO的问题嘛), 但是在程序中完全可⾏, 因为程序猿可以根据需要控制程序指定抛出任何1个异常.但是这段代码编译失败, 因为IOException 不是 RuntimeException的派⽣类.java规定:5.3.1 如果⼀个⽅法⾥利⽤throw⼿动抛出1个⾮RuntimeException异常, 必须在函数定义声明⾥加上throws 后缀改成这样就正确了:[java]1. public int f(int a, int b) throws IOException{2. if (0 == b){3. throw new IOException("Shit !!! / by zero!");4. }5.6. return a/b;7. }注意在⽅法定义⾥加上了throws⼦句. 告诉调⽤它的函数我可能抛出这个异常.5.3.2 调⽤该⽅法的⽅法则必须处理这个异常例如抄回上⾯的例⼦, g()调⽤f()函数.[java]1. public void g(){2. int i;3. h();4. i = f(); //recevie excepton5. k()6. }但是编译失败.因为f()利⽤throws 声明了会抛出1个⾮runtimeExcetpion. 这时g()必须做出处理.处理⽅法有两种:1. try catch⾃⼰处理:[java]1. public void g(){2. int i = 0;3. h();4. try{5. i = f(); //recevie excepton6. }7. catch(IOException e){8.9. }10. k();11. }需要注意的是, catch⾥⾯要么写上throws对应的异常(这⾥是 IOException), 要么写上这个异常的超类, 否则还是编译失败.2.g()利⽤throws 往上⼀级⽅法抛.[java]1. public void g() throws IOException{2. int i = 0;3. h();4. i = f(); //recevie excepton5. k();6. }这是调⽤g()的函数也要考虑上⾯的这两种处理⽅法了...但是最终上级的⽅法(main ⽅法)还是不处理的话, 就编译失败, 上⾯说过了, ⾮runtimeException⽆法抛给jvm处理.虽然这两种处理⽅法都能通过编译, 但是运⾏效果是完全不同的.第⼀种, g()能完整执⾏.第⼆种, g()被中断, 也就是g()⾥⾯的k(); 执⾏失败.5.4 throws 的语法.throws稍微⽐throw难理解点:语法是:public void f() throws Exception1, Exception2...{}也就是讲, thorws可以加上多个异常, 注意这⾥抛出的不是对象, 不能加上new.⽽且不是告诉别⼈这个函数有可能抛出这么多个异常. ⽽是告诉别⼈, 有可能抛出这些异常的其中⼀种.5.5 throws 的作⽤.如果为f()函数加上throws后续, 则告诉调⽤f()的⽅法, f()函数有可能抛出这些异常的⼀种.如果f()throws 了1个或若⼲个⾮RuntimeException, 则调⽤f()的函数必须处理这些⾮RuntimeException, 如上⾯的g()函数⼀样.如果f() throws的都是RuntimeException, 则调⽤f()的函数可以不处理, 也能通过编译, 但是实际上还是强烈建议处理它们.实际上, 如果1个⽅法f() throws A,B那么它有可能不抛出任何异常.(程序运⾏状态良好)也有能抛出C异常(应该避免, 最好在throws上加上C)5.6 什么时候应该⽤throws5.6.1 ⼀个函数体⾥⾯⼿动throw了1个RumtimeException, 则这个函数的定义必须加上throws⼦句这个是强制, 告诉别⼈这个函数内有炸弹.5.6.2 ⼀个函数内有可能由系统抛出异常.这个是⾮强制的, 但是如果你知道⼀个函数内的代码有可能抛出异常, 最好还是写上throws 后缀⽆论这个异常是否runtimeExcepion.5.7 ⼀般情况下,调⽤1个带有throws⽅法时怎么办个⼈建议, 如果你调⽤1个函数throws A, B, C那么你就在当前函数写上catch(A)catch(B)catch(C)catch(Exception)这样能处理能保证你的函数能完整执⾏, 不会被收到的异常中断.当然如果你允许你的函数可以被中断, 那么就可以在当前函数定义加上throws A, B 继续抛给上⼀级的函数.5.8 重写⽅法时, throws的范围不能⼤于超类的对应⽅法.例如你在⼀个派⽣类重写⼀个⽅法f(), 在超类⾥的f() throws A, B 你重写⽅法时就不throws出 A,,B,C 或者throws A和B的超类.原因也是由于多态的存在.因为1个超类的引⽤可以指向1个派⽣类的对象并调⽤不同的⽅法. 如果派⽣类throws的范围加⼤那么利⽤多态写的代码的try catch就不再适⽤.六, throw和throws⼀些主要区别.⾯试问得多,单独拉出来写了:6.1 throw 写在函数体内, throws写在函数定义语句中.应付⾯试官.6.2 throw 是抛出1个异常对象, throws是有能抛出异常的种类所以throw后⾯的⼀般加上new 和exception名字().⽽throws后⾯不能加上new的6.3 ⼀个⽅法最多只能throw1个异常, 但是可以throws多个种类异常因为⼀旦⼀个函数throw出1个异常, 这个函数就会被中断执⾏, 后⾯的代码被放弃, 如果你尝试在函数内写两个throw, 编译失败.⽽throws 是告诉别⼈这个函数有可能抛出这⼏种异常的⼀种. 但是最多只会抛出⼀种.6.4 如果在⼀个函数体内throw 1个⾮runtimeException, 那么必须在函数定义上加上throws后缀. 但反过来就不是必须的.原因上⾯讲过了.七, ⾃定义异常.我们可以⾃定义异常, 只需要编写1个类, 继承1个异常类就ok例⼦:[java]1. package Exception_kng;2.3. class User_Exception1 extends ArithmeticException{4. public User_Exception1(String Exception_name){5. super(Exception_name);6. }7.8. public void printStackTrace(){ //overwrite9. super.printStackTrace();10. System.out.printf("hey man, i am an user_defined excetpion\n");11. }12. }13.14. class Exp6{15. public int f(int a, int b){16. if (0 == b){17. throw new User_Exception1("Shit !!! / by zero!"); //use User_defined exception18. }19.20. return a/b;21. }22. }23.24. public class Expt_6{25. public static void g() {26. Exp6 ex = new Exp6();27. int i = 22;28. try{29. i = ex.f(8,0); //throw excetpion30. }catch(User_Exception1 e){31. e.printStackTrace();32. }33. System.out.printf("i is %d\n", i);34. System.out.printf("g() is done!!\n");35. }36. }上⾯的类User_Exception1 就是1个⾃定义异常, 并重写了printStackTrace()⽅法.⼋,java异常的优缺点.8.1 c语⾔是如何处理程序错误的.我们要理解异常的优缺点, ⾸先看看没有异常的是如何处理错误的.下⾯是个例⼦:[cpp]1. //openfile2. if (fileOpen() > 0){3. //check the length of the file4. if (gotLengthOfTheFile() > 0){5. //check the memory6. if (gotEnoughMemory() > 0){7. //load file to memory8. if (loadFileToMem() > 0){9. readFile();10. }else{11. errorCode = -5;12. }13.14. }else{15. errorCode = -5;16. }17.18. }else{19. errorCode = -5;20. }21.22. }else{23. errorCode = -5;24. }25.26. //handle error27. case errorCode....28.29. //release Source30. releaseSource();可以见到处理错误有这些特点1. ⼤部分精⼒都在错误处理.2. 需要把各种可能出现的错误全部考虑到, 才能保证程序的稳定性.3. 程序可读性差, 错误处理代码混杂在其他代码中.4. 出错返回信息少, ⼀旦出错难以调试.5. ⼀旦出现了未考虑到的错误, 资源释放代码⽆法执⾏.8.2 java异常机制下是如何编写上述代码的.[java]1. try{2. fileOpen();3. gotLengthOfTheFile();4. gotEnoughMemory();5. loadFileToMem();6. readFile();7. }8. catch(fileOpenFail) { handle1()}9. catch(gotLengthOfTheFileFail) { handle2()}10. catch(gotEnoughMemoryFail) { handle3()}11. catch(loadFileToMemFail) { handle4()}12. catch(readFileFail) { handle4()}13. catch(Exception e) { handle5()} //catch unexpected error14. finally{15. releasSource();16. }8.3 java异常机制的优点:由上⾯的代码可以看出部分优点:1. 业务代码和错误处理代码分离.2. 强制程序猿考虑程序的稳定性.3. 有利于代码调试(异常信息)4. 即使任何异常产⽣, 能保证占⽤的释放(finally)8.4 java异常机制的缺点:1. 异常嵌套难免影响代码可读性2. 并不能令程序逻辑更加清晰.3. 异常并不能解决所有问题。