java的一个x360ce报错exceptionn,为何会报错啊

博客分类:
一、在finally块中做数据回收操作
比如数据库连接都是很宝贵的,所以最好在finally中关闭连接。
JDBCAgent jdbc = new JDBCAgent();
jdbc.excute("select * from ctp_log");
}catch(SQLException e){
jdbc.close();
二、不要在异常finally块中定义返回值
如下代码,虽然有很多返回值,但如果真的执行,该代码的返回值永远是3,因为finally是最终执行代码,将其它返回值全部覆盖了!
if(x = 1){
return throw new RuntimeException();
}catch(Exception e){
三、覆写Exception的fillInStackTrace方法能提高异常性能
异常性能差是因为fillInStackTrace方法,该方法是带锁的并且需要填充线程异常栈信息。
而我们的业务类异常是不需要记录异常栈的,可以考虑覆写fillInStackTrace方法减小性能开支(据说覆写该方法能提高10倍性能)。
(注:什么是业务类,参照第四点)
public class AccountException extends Exception {
public Throwable fillInStackTrace() {
四、业务上的错误使用异常更加OOP
以登录为例,简单的登录方法通过返回boolean即可确认是否登录成功,但如果功能日趋复杂怎么办?通过抛出业务类异常的方式来解析错误信息可读性非常好。
userManager.login(account,passowrd,identify);
}catch(AccountException e){
//账号出错
}catch(PasswordException e){
//密码出错
}catch(IdentifyException e){
//验证码错误
}catch(AccountDisableException e){
//账号被禁用
五、使用正确的log记录异常信息
Log logger = LogFactory.getLog(Demo.class);
}catch(SQLException e){
throw new BusinessException(e);
//√发生该异常会影响后续数据完整性的时候,应该抛出中止操作
logger.error(e.getLocalizedMessage(),e);
//√记录完整的log日志方便调试
log.error(e);
//×这种记录方式只能记录很少的异常信息(连异常发生的位置都没有,记了白记)
e.printStackTrace();
//×仅仅将异常打到控制台,开发调试还可以,一旦到生产环境就很难跟踪异常
System.out.print(e);
六、除了记录异常,记得记录详细参数信息
很多时候通过logger.error(e.getLocalizedMessage(),e)这种记录日志的方式都不一定分析出异常原因。
比如出现一个SQL异常,log日志可能会这样提示:ORA-00936: 缺少表达式。试问这样的错误你能分析这句SQL到底哪儿出了问题吗?不能!所以记录日志的时候最好是把SQL及参数都打印出来,如下例所示。
但记录日志要有分寸,别把客户的机密信息记录出来,如果被发现,我们会负责的!
public List find(Long id,String name){
String sql = ......;
JdbcAgent.excute(sql);
}catch(Exception e){
logger.error("sql异常:"+sql+" 参数ID:"+id+",参数name:"+name,e);
(注:作为研发你可能会说:我通过Eclipse debugger调试就可以知道原因了。但从长远考虑:假如系统已经部署到客户环境上,他们允许你debugger调试吗?不能!所以最好的求助工具就是详细的log日志!)
七、从子到父顺序捕获异常
如下所示,假如抛出的是BusinessException异常,那么第二个catch就能捕获到。
如果catch(Exception e)在catch(BusinessException e)之前,则该异常会被catch(Exception e)捕获而不会进catch(BusinessException e)。
}catch(RuntimeException e){
}catch(BusinessException e){//BusinessException extends Exception
}catch(Exception e){
八、使用isInfoEnabled和isDebugEnabled
在看spring和apache等开源体系下的代码时,你会发现在记录log日志时总是看到如下风格的代码:
if (logger.isDebugEnabled()) {
logger.debug("Published root WebApplicationContext as ServletContext attribute with name [" +WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE + "]");
if (logger.isInfoEnabled()) {
long elapsedTime = System.currentTimeMillis() - startT
("Root WebApplicationContext: initialization completed in " + elapsedTime + " ms");
为什么记录debug和info日志前要加个判断?其实原因很简单:提高效率!如上代码所示,在记录日志时进行了字符串拼接,要知道这是会消耗一定资源的。假如当前log日志级别是error,则debug和info是不会被输出的,如果加了if判断则log.debug/info中的字符串拼接就不会执行,自然提高了效率。
在小系统看不出差距,但如果是高并发的系统下,少执行一句代码能明显减小服务器的压力,精细化的代码是有必要的!
注意:下面这样的代码是提高不了性能的,因为在if之前就已经准备好log信息:
long elapsedTime = System.currentTimeMillis() - startT
String info = "Root WebApplicationContext: initialization completed in " + elapsedTime + " ms";
if (logger.isInfoEnabled()) {
浏览 10764
浏览: 2296468 次
来自: 成都
1987_ming 写道1987_ming 写道System. ...
你那个“2004年Nutch创始人Doug Cutting基于 ...
我的就是这么弄得,到了页面还是那个格式的 。
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'一.&异常的定义
在《java编程思想》中这样定义&异常:阻止当前方法或作用域继续执行的问题。虽然java中有异常处理机制,但是要明确一点,决不应该用"正常"的态度来看待异常。绝对一点说异常就是某种意义上的错误,就是问题,它可能会导致程序失败。之所以java要提出异常处理机制,就是要告诉开发人员,你的程序出现了不正常的情况,请注意。
记得当初学习java的时候,异常总是搞不太清楚,不知道这个异常是什么意思,为什么会有这个机制?但是随着知识的积累逐渐也对异常有一点感觉了。举一个例子来说明一下异常的用途。
public class Calculator {
public int devide(int num1, int num2) {
//判断除数是否为0
if(num2 == 0) {
throw new IllegalArgumentException("除数不能为零");
return num1/num2;
看一下这个类中关于除运算的方法,如果你是新手你可能会直接返回计算结果,根本不去考虑什么参数是否正确,是否合法(当然可以原谅,谁都是这样过来的)。但是我们应尽可能的考虑周全,把可能导致程序失败的"苗头"扼杀在摇篮中,所以进行参数的合法性检查就很有必要了。其中执行参数检查抛出来的那个参数非法异常,这就属于这个方法的不正常情况。正常情况下我们会正确的使用计算器,但是不排除粗心大意把除数赋值为0。如果你之前没有考虑到这种情况,并且恰巧用户数学基础不好,那么你完了。但是如果你之前考虑到了这种情况,那么很显然错误已在你的掌控之中。
二.&异常扫盲行动
今天和别人聊天时看到一个笑话:世界上最真情的相依,是你在try我在catch。无论你发神马脾气,我都默默承受,静静处理。&大多数新手对java异常的感觉就是:try...catch...。没错,这是用的最多的,也是最实用的。我的感觉就是:java异常是从"try...catch..."走来。
首先来熟悉一下java的异常体系:
Throwable&类是&Java&语言中所有错误或异常的超类(这就是一切皆可抛的东西)。它有两个子类:Error和Exception。
Error:用于指示合理的应用程序不应该试图捕获的严重问题。这种情况是很大的问题,大到你不能处理了,所以听之任之就行了,你不用管它。比如说VirtualMachineError:当&Java&虚拟机崩溃或用尽了它继续操作所需的资源时,抛出该错误。好吧,就算这个异常的存在了,那么应该何时,如何处理它呢??交给JVM吧,没有比它更专业的了。
Exception:它指出了合理的应用程序想要捕获的条件。Exception又分为两类:一种是CheckedException,一种是UncheckedException。这两种Exception的区别主要是CheckedException需要用try...catch...显示的捕获,而UncheckedException不需要捕获。通常UncheckedException又叫做RuntimeException。《effective&java》指出:对于可恢复的条件使用被检查的异常(CheckedException),对于程序错误(言外之意不可恢复,大错已经酿成)使用运行时异常(RuntimeException)。
我们常见的RuntimeExcepiton有IllegalArgumentException、IllegalStateException、NullPointerException、IndexOutOfBoundsException等等。对于那些CheckedException就不胜枚举了,我们在编写程序过程中try...catch...捕捉的异常都是CheckedException。io包中的IOException及其子类,这些都是CheckedException。
三.&异常的使用
在异常的使用这一部分主要是演示代码,都是我们平常写代码的过程中会遇到的(当然只是一小部分),抛砖引玉吗!
例1.&这个例子主要通过两个方法对比来演示一下有了异常以后代码的执行流程。&
public static void testException1() {
int[] ints = new int[] { 1, 2, 3, 4 };
System.out.println("异常出现前");
System.out.println(ints[4]);
System.out.println("我还有幸执行到吗");// 发生异常以后,后面的代码不能被执行
} catch (IndexOutOfBoundsException e) {
System.out.println("数组越界错误");
System.out.println("异常出现后");
异常出现前
数组越界错误
异常出现后
public static void testException2() {
int[] ints = new int[] { 1, 2, 3, 4 };
System.out.println("异常出现前");
System.out.println(ints[4]);
System.out.println("我还有幸执行到吗");// 发生异常以后,他后面的代码不能被执行
首先指出例子中的不足之处,IndexOutofBoundsException是一个非受检异常,所以不用try...catch...显示捕捉,但是我的目的是对同一个异常用不同的处理方式,看它会有什么不同的而结果(这里也就只能用它将就一下了)。异常出现时第一个方法只是跳出了try块,但是它后面的代码会照样执行的。但是第二种就不一样了直接跳出了方法,比较强硬。从第一个方法中我们看到,try...catch...是一种"事务性"的保障,它的目的是保证程序在异常的情况下运行完毕,同时它还会告知程序员程序中出错的详细信息(这种详细信息有时要依赖于程序员设计)。
例2.&重新抛出异常
public class Rethrow {
public static void readFile(String file) throws FileNotFoundException {
BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));
} catch (FileNotFoundException e) {
e.printStackTrace();
System.err.println("不知道如何处理该异常或者根本不想处理它,但是不做处理又不合适,这是重新抛出异常交给上一级处理");
//重新抛出异常
public static void printFile(String file) {
readFile(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
public static void main(String[] args) {
printFile("D:/file");
异常的本意是好的,让我们试图修复程序,但是现实中我们修复的几率很小,我们很多时候就是用它来记录出错的信息。如果你厌倦了不停的处理异常,重新抛出异常对你来说可能是一个很好的解脱。原封不动的把这个异常抛给上一级,抛给调用这个方法的人,让他来费脑筋吧。这样看来,java异常(当然指的是受检异常)又给我们平添很多麻烦,尽管它的出发点是好的。
例3.&异常链的使用及异常丢失
定义三个异常类:ExceptionA,ExceptionB,ExceptionC
public class ExceptionA extends Exception {
public ExceptionA(String str) {
public class ExceptionB extends ExceptionA {
public ExceptionB(String str) {
super(str);
public class ExceptionC extends ExceptionA {
public ExceptionC(String str) {
super(str);
异常丢失的情况:
public class NeverCaught {
static void f() throws ExceptionB{
throw new ExceptionB("exception b");
static void g() throws ExceptionC {
} catch (ExceptionB e) {
ExceptionC c = new ExceptionC("exception a");
public static void main(String[] args) {
} catch (ExceptionC e) {
e.printStackTrace();
exception.ExceptionC
at exception.NeverCaught.g(NeverCaught.java:12)
at exception.NeverCaught.main(NeverCaught.java:19)
为什么只是打印出来了ExceptionC而没有打印出ExceptionB呢?这个还是自己分析一下吧!
上面的情况相当于少了一种异常,这在我们排错的过程中非常的不利。那我们遇到上面的情况应该怎么办呢?这就是异常链的用武之地:保存异常信息,在抛出另外一个异常的同时不丢失原来的异常。
public class NeverCaught {
static void f() throws ExceptionB{
throw new ExceptionB("exception b");
static void g() throws ExceptionC {
} catch (ExceptionB e) {
ExceptionC c = new ExceptionC("exception a");
c.initCause(e);
public static void main(String[] args) {
} catch (ExceptionC e) {
e.printStackTrace();
exception.ExceptionC
at exception.NeverCaught.g(NeverCaught.java:12)
at exception.NeverCaught.main(NeverCaught.java:21)
Caused by: exception.ExceptionB
at exception.NeverCaught.f(NeverCaught.java:5)
at exception.NeverCaught.g(NeverCaught.java:10)
... 1 more
这个异常链的特性是所有异常均具备的,因为这个initCause()方法是从Throwable继承的。
例4.&清理工作
清理工作对于我们来说是必不可少的,因为如果一些消耗资源的操作,比如IO,JDBC。如果我们用完以后没有及时正确的关闭,那后果会很严重,这意味着内存泄露。异常的出现要求我们必须设计一种机制不论什么情况下,资源都能及时正确的清理。这就是finally。
public void readFile(String file) {
BufferedReader reader =
reader = new BufferedReader(new InputStreamReader(
new FileInputStream(file)));
// do some other work
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
reader.close();
} catch (IOException e) {
e.printStackTrace();
例子非常的简单,是一个读取文件的例子。这样的例子在JDBC操作中也非常的常见。(所以,我觉得对于资源的及时正确清理是一个程序员的基本素质之一。)
Try...finally结构也是保证资源正确关闭的一个手段。如果你不清楚代码执行过程中会发生什么异常情况会导致资源不能得到清理,那么你就用try对这段"可疑"代码进行包装,然后在finally中进行资源的清理。举一个例子:
public void readFile() {
BufferedReader reader =
reader = new BufferedReader(new InputStreamReader(
new FileInputStream("file")));
// do some other work
//close reader
reader.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
我们注意一下这个方法和上一个方法的区别,下一个人可能习惯更好一点,及早的关闭reader。但是往往事与愿违,因为在reader.close()以前异常随时可能发生,这样的代码结构不能预防任何异常的出现。因为程序会在异常出现的地方跳出,后面的代码不能执行(这在上面应经用实例证明过)。这时我们就可以用try...finally来改造:
public void readFile() {
BufferedReader reader =
reader = new BufferedReader(new InputStreamReader(
new FileInputStream("file")));
// do some other work
// close reader
} finally {
reader.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
及早的关闭资源是一种良好的行为,因为时间越长你忘记关闭的可能性越大。这样在配合上try...finally就保证万无一失了(不要嫌麻烦,java就是这么中规中矩)。
再说一种情况,假如我想在构造方法中打开一个文件或者创建一个JDBC连接,因为我们要在其他的方法中使用这个资源,所以不能在构造方法中及早的将这个资源关闭。那我们是不是就没辙了呢?答案是否定的。看一下下面的例子:
public class ResourceInConstructor {
BufferedReader reader =
public ResourceInConstructor() {
reader = new BufferedReader(new InputStreamReader(new FileInputStream("")));
} catch (FileNotFoundException e) {
e.printStackTrace();
public void readFile() {
while(reader.readLine()!=null) {
//do some work
} catch (IOException e) {
e.printStackTrace();
public void dispose() {
reader.close();
} catch (IOException e) {
e.printStackTrace();
这一部分讲的多了一点,但是异常确实是看起来容易用起来难的东西呀,java中还是有好多的东西需要深挖的。
四.&异常的误用
对于异常的误用着实很常见,上一部分中已经列举了几个,大家仔细的看一下。下面再说两个其他的。
例1.&用一个Exception来捕捉所有的异常,颇有"一夫当关万夫莫开"的气魄。不过这也是最傻的行为。
public void readFile(String file) {
BufferedReader reader =
Connection conn =
reader = new BufferedReader(new InputStreamReader(
new FileInputStream(file)));
// do some other work
conn = DriverManager.getConnection("");
} catch (Exception e) {
e.printStackTrace();
} finally {
reader.close();
conn.close();
} catch (Exception e) {
e.printStackTrace();
从异常角度来说这样严格的程序确实是万无一失,所有的异常都能捕获。但是站在编程人员的角度,万一这个程序出错了我们该如何分辨是到底是那引起的呢,IO还是JDBC...所以,这种写法很值得当做一个反例。大家不要以为这种做法很幼稚,傻子才会做。我在公司实习时确实看见了类似的情况:只不过是人家没有用Exception而是用了Throwable。
例2.&这里就不举例子了,上面的程序都是反例。异常是程序处理意外情况的机制,当程序发生意外时,我们需要尽可能多的得到意外的信息,包括发生的位置,描述,原因等等。这些都是我们解决问题的线索。但是上面的例子都只是简单的printStackTrace()。如果我们自己写代码,就要尽可能多的对这个异常进行描述。比如说为什么会出现这个异常,什么情况下会发生这个异常。如果传入方法的参数不正确,告知什么样的参数是合法的参数,或者给出一个sample。
例3.&将try&block写的简短,不要所有的东西都扔在这里,我们尽可能的分析出到底哪几行程序可能出现异常,只是对可能出现异常的代码进行try。尽量为每一个异常写一个try...catch,避免异常丢失。在IO操作中,一个IOException也具有"一夫当关万夫莫开"的气魄。
总结非常简单,不要为了使用异常而使用异常。异常是程序设计的一部分,对它的设计也要考究点。
阅读(...) 评论()博客分类:
深入讨论Java开发异常的处理
(深刻讨论异常的帖子,保存以免丢失,版权归帖子所有人)
发表时间:
关于 Java 中引入的 Checked Exceptions,目前存在着很多反对意见。正方的观点是引入 Checked Exceptions,可以增加程度的鲁棒性。反方的观点是 Checked Exceptions 很少被开发人员正确使用过,并且降低了程序开发的生产率和代码的执行效率。 正方代表 James Gosling
反方代表 Anders Hejlsberg
中文版: 两位都是大师级的人物,观点的碰撞非常精彩。 我个人更倾向于 James Gosling 的观点,即稳定性更加重要。C++ 程序的后期维护成本远远高于 Java 程序,更不要说前期的开发成本了。Java 要担负企业级的核心应用(HA 24X7),没有这些系统级的保证是不可能的。C++、Delphi 都中没有 Checked Exceptions,所以 Anders 设计 C# 时也没有加 Checked Exceptions。当然我并不是说没有 Checked Exceptions 就一定不能写出稳定的程序(你说,我就是比你牛,我用汇编语言都能写出稳定的程序!),但是显然使用 Java 语言写出稳定的程序比用 C++ 更容易。Checked Exceptions 就是编程语言所提供的系统级保证,能否用好是你自己的问题了,并不象 Anders 说的那样严重。我觉得 Anders 大师对于企业级应用并没有太多的概念。James Gosling 看了 C# 的设计后觉得不过如此。当然这只是大师本人的观点,我们未必一定要接受了。
发表时间:
我没有资格评论大师们的观点,但是我知道绝大多数的Java程序员根本就没有领悟“Exception”的真正用处。他们就是把Exception当做异常来理解,没有明白Exception实际上代表了一个UseCase中的异常流的处理。 在使用UseCase来描述一个场景的时候,有一个主事件流和n个异常流。异常流可能发生在主事件流的过程,而try语句里面实现的是主事件流,而catch里面实现的是异常流,在这里Exception不代表程序出现了异常或者错误,Exception只是面向对象化的业务逻辑控制方法。如果没有明白这一点,那么我认为并没有真正明白应该怎么使用Java来正确的编程。 而我自己写的程序,会自定义大量的Exception类,所有这些Exception类都不意味着程序出现了异常或者错误,只是代表非主事件流的发生的,用来进行那些分支流程的流程控制的。例如你往权限系统中增加一个用户,应该定义1个异常类,UserExistedException,抛出这个异常不代表你插入动作失败,只说明你碰到一个分支流程,留待后面的catch中来处理这个分支流程。传统的程序员会写一个if else来处理,而一个合格的OOP程序员应该有意识的使用try catch 方式来区分主事件流和n个分支流程的处理,通过try catch,而不是if else来从代码上把不同的事件流隔离开来进行分别的代码撰写。 总之 Exception && 异常 BTW:我是支持BE和JG的观点的。我以前在接触C#的时候,就很奇怪C#的这一点了,Anders有他的理由,但是我认为一个良好的面向对象的软件是应该强制使用Exception的。
发表时间:
robbin 的话加深了我对于 Exception 的理解。我觉得 try...catch...finally 对于我是一个很好的约束,帮助我编写出更高质量的代码。好象我走路的拐杖一样,我在 Eclipse 中写程序也比在 UltraEdit 中写程序效率高得多,因为 Eclipse 对于我写的代码有更高的要求,UltraEdit 几乎没有任何要求。我很少直接使用 throws Exceptions 把所有 Exceptions 都甩出去的。你不知道程序员有多懒,如果不强制要求,我敢打赌他们 90% 的场合下是完全不用 Exception。
发表时间:
另外纠正一个错误的观点:很多人喜欢定义方法的返回类型为boolean型的,当方法正确执行,没有出错的时候返回true,而方法出现出现了问题,返回false。这在Java编程当中是大错而特错的! 方法的返回值只意味着当你的方法调用要返回业务逻辑的处理结果的。如果业务逻辑不带处理结果,那么就是void的,不要使用返回值boolean来代表方法是否正确执行。 例如 用户登陆方法
boolean login(String username, String password);;
很多人喜欢用boolean返回,如果是true,就是login了,如果false就是没有登陆上。其实是错误的。还有的人定义返回值为int型的,例如如果正确返回就是0,如果用户找不到就是-1,如果密码不对,就是-2
int login(String username, String password);;
然后在主程序里面写一个if else来判断不同的流程。
int logon = UserManager.login(xx,xx);;
if (logon ==0); {
} else if (logon == 1); {
} else if (logon ==2); {
这是面向过程的编程逻辑,不是面向对象的编程逻辑。 应该这样来写:
User login(String username, String password); throws UserNotFoundException, PasswordNotMatchE
主程序这样来写:
UserManager.login(xx,xx);;
用户登陆以后的主事件流代码
} catch (UserNotFoundException e); {
用户名称没有的事件处理,例如产生一个提示用户注册的页面
} catch (PasswordNotMatchException e); {
密码不对的事件处理,例如forward到重新登陆的页面
发表时间:
我想应该分两个问题来讨论: 1。什么时候抛出异常--涉及到服务类 2。抛出checked还是unchecked的异常--涉及到客户类 对第一个问题来说,我想异常本身这个字解释了某些东西,异常就是我们认为在正常情况下不可能发生的问题,并且服务代码不知道如何去处理。譬如说我做一个监控程序,需要用压缩卡提供的API去初始化所有的板卡,API提供的是boolean型的返回值,但我把这个API变成抛出一个异常,因为除非特殊原因,我不认为会发生初始化失败的情况,当然更不知道怎样去处理这个问题。又譬如Hibernate里面的LoadObject使用没有发现这个对象存在,那Hibernate也是认为不可能的,除非其他代码直接删除了数据库里面的记录,那么也需要抛出异常。当然Hibernate本身也不知道如何处理这种情况。 但是如果发生的情况是可以预期的,那我不认为应该抛出例外。象上面这个userExist的情况,我认为应该在前面已经分流,应该首先判断这个用户是否存在,if(userExists()),然后进行处理,而不应当抛出例外。以及login应当返回true或者false。也就是说,这些属于程序的正常流程,而不是例外,不是异常。把例外作为正常程序流程的控制机制,只不过是把服务代码中的if转移到客户代码去,没有减少任何需要处理的代码,反而增加了系统的负担(生成例外栈)。 还有抛出异常的情况是违反方法的先决条件,每一个方法都有自己的先决条件和后置条件,方法只有在正确的前提下才能执行达到一个正确的后果,(所谓类的不变量)。譬如你去存取一个数组的某一个元素,这个存取方法有一个前提条件,就是你的索引应当落入它的最大下标和最小下标之间,不然就应当抛出一个例外。 对于第二个问题,端视于客户代码是否能够根据这个例外进行合理的处理。如果客户代码根本就不知道如何处理这个例外,应当把它作为一个unchecked例外,例如上面下标的问题,客户代码用一个不合法的下标来存取数组,那么抛出一个checked例外以后,客户代码是+1还是-1?显然根本就不可能做出“合理的”处理,客户既然不能处理,还要强制它去处理,那么就是捕获,打印了事,没有增加任何价值。但是如果是客户可以处理的,或者可以选择不同的方式处理的,那么就可能需要用checked,但我发现很少有这样的情况。对于类似于RemoteException或者SQLException这些Exception,我一般都转换为具体的业务Exception,而我所有的业务Exception都是RuntimeException. 所以我的观点是,是否抛出例外就是服务代码是否进行合理的处理,抛出什么类型的例外就是客户代码是否能够合理的处理。 当然,Exception应当是有层次的,我的Snip上面有一些说明。
发表时间:
我觉得 potian 说的很对。因为性能以及 Exception 设计目的上的原因,不应该用 Exception 来处理本来有可能发生的流程。Exception 就是用来处理真正的异常的。另外 Exception 用得过多对于性能有很大影响,所以要慎重使用。要把 Exception 设计作为整个 OOAD 设计中重要的一部分来考虑。所以我们得到的结论不是 Java 中是否应该引入 Checked Exceptions 的问题,而是如何用好 Checked Exceptions 的问题。 以前我还买过《Design by Contract 原则与实践》,里面讲的开发方法就更加怪了,可以说整个是一个基于断言的开发方法。好在 JDK 1.4 以后已经提供了 Assert,否则用 Java 是无法实现 DbC 的。目前直接支持这种开发方法的语言好象只有 Eiffel。书中的例子一半用 Eiffel,一半用 Java 的。
发表时间:
在用例里面,主事件流也被称为愉快的(Happy)流程,就是说这个过程使使用者和系统都感到愉快,皆大欢喜,它是需求分析时首先考虑的内容,UML鼓励我们先集中精力解决主要问题,对不同的问题(主事件流、异常事件流)分别进行分析,各个击破。Java的Exception机制与UML的思想是一致的。我说Exception不等于错误也是这个意思。在我们的系统中登录的接口就是会分别抛出用户不存在和密码无效的异常,这时业务逻辑层需要考虑的事情,表示逻辑不需要分别捕捉、分别处理,有专门的错误页面去根据异常类显示不同的提示信息。
发表时间:
我认为函数抛不抛异常与函数本身的语义密切相关,在函数正常返回的情况下,函数完成了其即定的语义,在返回异常时,说明函数不能顺利地完成语义。因此login函数当然应该有UserNotFoundException异常,因为login函数的语义就是用户登录,而不是看用户是否存在;isUserExist当然就应当返回boolean,因为它就是用来检查用户是否存在的,而不需要抛出异常来表明。
这是对的,如果你写的login(user,password)返回一个UserDTO,那么就应该抛出例外,因为你这个方法预期将返回一个正常的User。(这适合于普通的登陆界面,直接把这个UserDTO放到Session里面去) 如果你的login是为了判断能不能成功,那就不是例外。这种情况也很多,譬如登陆以后需要根据目前的用户状态判断是否要改用户补充信息、确认等等。这时候往往第一步判断是否成功,后面根据不同的状态取得不同的用户信息 例外是处理异常的情况,和你类(服务类)的意图密切相关,同一种情况,在某些方法里面是例外,而在另外方法里面就不是例外了。
所以我不太喜欢第一种方式,因为第一种方式实际上在同一个方法中包含了两个责任,验证是否合法以及验证合法以后返回用户信息。这造成了验证合法不能被细粒度重用(如我第二种情况,当我需要不同的用户信息时)。当然,在一个不需要进行多步认证的应用程序里面,这已经足够了,可以等到第二种情况出现的时候才去重构。
发表时间:
重新看了一遍大家的讨论,我又回顾了一下自己目前正在做的这个项目,像是又有了一些新的领悟,请指正: 我们这里的人大多是做应用的,而不是做组件、框架的,这两类开发需要的思路可能不太一样。 从做应用的角度看,我希望利用异常来管理显示在用户面前的错误提示,这样我就会将异常划分为两类,一类是可以显示给用户看的,或者说用户可以看的懂的,一类是给维护人员看的,就是通常说的系统错误,可以想象,让用户看到“空指针异常”是极不友好的行为。我们的项目中有一个专门显示错误的页面,它要么显示有具体业务含义的错误,要么就显示“系统错误”(然后维护人员可以从log中查找错误)。而前一类错误里面,每种错误总有一个不同的异常类和它对应,或者说,业务逻辑方法向表示逻辑抛出的异常,表示逻辑不需要分别处理(不要显示错误的除外),一律交给错误页面(其实是ErrorPageUIAction,我们用Struts),错误页面看是什么异常就显示什么错误提示,这里错误页面需要一个XML,XML里面定义了异常和错误提示的对应关系,当然XML里面只能有用户异常,不在XML里面的异常错误页面就会显示“系统错误”。业务逻辑事先将用户异常登记到XML中,这样错误信息还可以单独、统一的维护。 上面讲的是将异常展示到错误页面的方法,这其实只涉及到最后一层(Action)捕捉异常和业务逻辑层抛出异常的问题,而如何中间层内的异常如何抛、如何捕捉的问题考虑的思路一定是不一样的,不过,做应用系统的,业务逻辑层内部交叉引用的不多,所以这一块异常设计的矛盾并不突出。而如果你正在开发高度重用的组件甚至框架,异常就一定要好好设计一下了。 至于组件、框架的异常如何设计,我想只要去学JDK、Hibernate的那一套东西就没错了。能想到的就是,异常一定是调用者可以理解的,和方法的语义密切相关的。 最后,回到最初的问题,Why Checked Exception?我们讨厌它的主要原因其实还是它太令人迷惑了,太多人虽然整天又抛又接的,其实根本就没弄明白这里面是怎么一回事,其实你只要用不了一下午的时间冷静下来,看看例子稍微思考一下,就一定可以弄的很透彻。Anders举的例子其实很可笑的,他说底层方法抛出4个异常,随着梯子越来越高,你的方法大概需要声明40个异常,其实他一定没有写过Java程序,更没有设计过Java方法,异常只需要对本层方法的调用者有意义,调用者根本就不需要关心底层错误的细节,那方法干吗还要声明那些底层抛的异常呢?一定是自己在方法里面消化掉了嘛!(需要调用者作为错误处理的异常合并抛一个异常)
muziq 看来是一个认真研究问题的人。Anders 确实有故意丑化 Java 的倾向。虽然我讨厌人身攻击,但是一些著名的大师也有掏糨糊的时候,毕竟都不是完人。所以我判断大师的标准就是看他在宣传自己的理论时是否有意在贬低别人的理论,如果是这样那他就不是我心目中的大师了。
发表时间:
1、异常有两种,一种是源于程序员的疏忽,一种是源于不可控的外力。有些程序员将其混为一谈,然后统一的在catch里忽略掉这种异常,是对自己的“放纵”。 2、需要捕捉的异常也有两种,一种是自己的程序抛出的,一种是系统抛出的。系统抛出的异常,没办法,必须一一处理好,但是自己的程序抛出的异常,不应该搞出复杂的异常继承体系出来,只需在异常中填入统一格式的Error Code,然后所有的程序,都统一catch这种异常,然后一律交给某个错误处理对象。而不是在自己的程序里,散布着各种各样的catch。 3、我们要追求的是程序的功能,而不是纯粹意义上的美感。
发表时间:
需要捕捉的异常也有两种,一种是自己的程序抛出的,一种是系统抛出的。系统抛出的异常,没办法,必须一一处理好,但是自己的程序抛出的异常,不应该搞出复杂的异常继承体系出来
什么叫做程序抛出的异常,什么叫做系统抛出的异常,你能明确界定吗?FileNotFoundException你说算是系统异常呢?还是程序异常?站在某些程序员的角度,他会觉得是系统异常,不过像我喜欢看JDK源代码的人来说,我对Sun的程序什么情况下抛出FileNotFoundException很清楚,这些代码对我来说,和我自己写的代码能有什么不同吗?对我来说,FileNotFoundException就是程序异常。既然JDK可以抛出异常,凭什么我就不能抛出异常? 站在底层程序员的角度来看,根本没有什么系统异常可言,否则的话,还不如不要定义任何异常得了,干脆就是函数调用返回值,你说为什么Sun不定义0,1,2这样的返回值,而是抛出异常呢?Java程序无非就是一堆class,JDK的class可以抛异常,我写的class为什么不能抛出? 异常不异常的界定取决于你所关注的软件层面,例如你是应用软件开发人员,你关心的是业务流程,那么你就应该捕获底层异常,你就应该定义业务层异常,向上抛出业务层异常。如果是底层程序员,你就应该定义和抛出底层异常。要不要抛出异常和抛出什么异常取决你站在什么软件层面了,离开这个前提,空谈异常不异常是没有意义的。
发表时间:
robbin 写道
什么叫做程序抛出的异常,什么叫做系统抛出的异常,你能明确界定吗?
程序抛出的异常,就是我自己的程序里抛出的Exception。系统的异常,就是我的控制范围之外的,封装好了的异常。这些异常,我甚至完全不知道它为什么会抛出来,只知道我必须一一处理掉。
robbin 写道
像我喜欢看JDK源代码的人来说,我对Sun的程序什么情况下抛出FileNotFoundException很清楚,这些代码对我来说,和我自己写的代码能有什么不同吗?
高手当然可以看人家的源代码,但是我的工作,或者说面向对象的原理,要求我的,只是理解一个对象的接口。 人家的程序,我没有办法,只能老老实实的处理各种各样的异常,但是自己的程序,只要约定清晰,为什么不能使自己轻松一些呢?
robbin 写道
你说为什么Sun不定义0,1,2这样的返回值,而是抛出异常呢?Java程序无非就是一堆class,JDK的class可以抛异常,我写的class为什么不能抛出?
因为0,1,2这样的值表达的含义不够丰富,但是作为返回值,又不合理。 ————函数有它的本身的返回值。 因此,返回一个异常,其实就是一个封装完好的,返回的对象。这个对象Type不是在函数名的前面说明,而是在一个更加特别的地方,函数的后面说明。这就是异常的本质————非正常的返回值。 这个返回值,为什么不能用传统的方法处理呢?因为Object x=method();表明它只能接受某一个特定的对象,如果出现Exception的对象,就会报错。因此需要catch来接手处理这样的返回值。 本质上来说,任何返回值,都没有对错之分,只不过是一个约定。在我看来,Exception("SQLException")与SQLException()没有什么实质上的区别。在实际的使用中,多用组合,少用继承,不是大师们谆谆告诫我们的吗? 因此我认为,SUN的JDK里的Exception的设计,并不合理,只应该有一个Exception对象,而不是搞出一堆让人眼花缭乱的Exception继承体系。而这样的继承体系,除了名字的不同,基本上没有任何区别。
发表时间:
pufan 写道
checked Exception 总是要throw到控制层的,不管你是直接throw,还是转换后throw,还是组合一个新异常throw,因为checked Exception是天灾人祸,你必须捕捉到给用户一个交代。试想,作为一个优秀的楼房架构设计师,他必须考虑到各种异常(天灾人祸)并作出预防措施:雷击怎么办,发洪水怎么办,地震怎么办,飞机撞又怎么办,还包括对各种底层异常的处理,有白蚁了怎么办,某处发生火灾了怎么办,这是对用户生命的负责。同样,我们做程序架构设计的同样要给用户一个交代,login时口令错了怎么办,ip地址非法怎么办,用户在他处已登录怎么办,黑客重复提交又怎么办,这同样也是对用户的负责。....
你大概忽略了系统的“层次”对于异常设计的影响,Robbin和我在前面都提到过这个问题:
robbin 写道
异常不异常的界定取决于你所关注的软件层面,例如你是应用软件开发人员,你关心的是业务流程,那么你就应该捕获底层异常,你就应该定义业务层异常,向上抛出业务层异常。如果是底层程序员,你就应该定义和抛出底层异常。要不要抛出异常和抛出什么异常取决你站在什么软件层面了,离开这个前提,空谈异常不异常是没有意义的。
另外,也建议你去参考一下《Effective Java》中关于“异常转义”的论述,个人认为那是非常精辟的见解,如果你手头找不到这本书的话我可以改天抄到这里。 庄表伟质疑了异常的继承,我也这么想过,异常之间的继承关系代表了什么语义呢?我认为异常继承的设计除了给API使用者添加理解的困难以外,并不会有什么积极的意义。不过,我不同意用一个Exception类取代所有异常类的说法,不用继承关系并不足以让我们摒弃异常类的设计,使用单独的类表示不同的异常可以使API的文档更加友好,更容易编写,捕捉异常的代码更易读。
发表时间:
1、我们知道,在Java语言中,一个函数的返回值类型只能有一个。如果在一个Class中,接受相同参数列的同名函数,有不同的返回值,那么编译器会明确的报错。因为如果这个函数的用户,调用了这个函数名,但是不要求任何返回值,那么jvm将不知道调用哪一个函数。 2、如果一个类继承了另一个父类,想要覆写父类的函数,这个必须与父类函数的返回类型一模一样,既不能是父类函数返回值的子类,也不能是那个返回值的父类。因为无论采用哪一种返回值,都有可能给它的使用者,带来困扰。因此编译器同样很坚决的报告了编译错误。 3、异常的本质,就是一个函数的非正常返回值。因此需要在函数名的后面,用throws来申明,而且也不能用return返回一个Exception对象,而是用throw来返回。 4、我们不可能想象这样的语法:对一个函数的返回值的不同的可能对象,做类似的Case的处理,因为那样会非常困扰,但是事实上,我们却在对一个函数的不同的Exception对象,进行着catch处理。 5、一个异常体系,可以想象成一棵树,一个函数后面的throws的说明,写出了n个异常,就不仅仅代表着这明确的n个异常,还代表着这n个异常的所有的子类的一个集合。而在这个函数的(在子类中的)覆写版本来说,它的throws的异常集合,只需要小于父类函数的异常集合,就能够编译通过。 6、但是,我们的throw(XXXException e)子句,又应该是这样的次序: try{ // }catch(SubSubSub1Exception e){ // }catch(SubSubSub2Exception e){ // }catch(SubSubException e){ // }catch(SubException e){ // }catch(Exception e){ // } 这样才能正确的,处理可能出现的异常,否则就有可能错过一个特定的异常,而对其只进行了大而化之的处理。 7、按照对象的概念,父对象可以当然的涵盖子对象。但是对于异常来说,子异常并不能被当然的当成父异常,而是应该被明确的特殊对待,否则申明一个子异常的就丧失了其本来的含义。于是我们就可以看见JAVA语言机制中存在的本质上的矛盾:新出现的子异常,可能不会被任何调用者发现(因为编译器不会报错,调用者也能大而化之的处理),而程序的本意,却被扭曲了。 8、如果我们关注异常的本质--(函数的非正常返回值)的话,那么我们就有理由相信,一个函数应该只返回一种异常,而且在它的子类的覆盖版本中,也不应该被改变。 9、进一步说,用一个不断继承的,没有任何实质上的功能代码的异常体系中,唯一有意义的,就是这个类的名称,我认为这是对面向对象概念的滥用。正确的用法是,一个系统中,只应该有一个Exception对象,这个对象应该设计为final。
发表时间:
庄表伟 写道
8、如果我们关注异常的本质--(函数的非正常返回值)的话,那么我们就有理由相信,一个函数应该只返回一种异常,而且在它的子类的覆盖版本中,也不应该被改变。 9、进一步说,用一个不断继承的,没有任何实质上的功能代码的异常体系中,唯一有意义的,就是这个类的名称,我认为这是对面向对象概念的滥用。正确的用法是,一个系统中,只应该有一个Exception对象,这个对象应该设计为final。
异常类可以定义方法来返回与错误相关的信息(还是参见《Effective Java》),要知道面向对象不只有继承这一个特性。 我想引出一个问题,喜欢设计的朋友可以一起探讨一下: 无论是Server side system还是Desktop system,都需要在特定的情况下显示错误信息给用户看,那么你的系统如何显示错误信息呢?异常能起到什么作用?
发表时间:
muziq 写道
异常类可以定义方法来返回与错误相关的信息(还是参见《Effective Java》),要知道面向对象不只有继承这一个特性。 我想引出一个问题,喜欢设计的朋友可以一起探讨一下: 无论是Server side system还是Desktop system,都需要在特定的情况下显示错误信息给用户看,那么你的系统如何显示错误信息呢?异常能起到什么作用?
一个异常类的确可以这样做,但是真的有人这么用了吗? 大多数人对于异常的使用,不过是因为可以有一个不同的异常类名。 有没有考虑过,为什么会出现这样的使用状况呢? 我认为Exception应该设计为final,就是因为目前的这个对象,已经基本上够用了。而且大多数人,也都认为够用了。
发表时间:
robbin 写道
另外纠正一个错误的观点:很多人喜欢定义方法的返回类型为boolean型的,当方法正确执行,没有出错的时候返回true,而方法出现出现了问题,返回false。这在Java编程当中是大错而特错的!
其实这种方法也说不上错,使用Exception的关键是,你站在什么样的角度来看这个问题。 如果你是一个API Designer,那么定义方法返回值的做法反而是提倡的,因为如果你在你的API里面抛出太多Checked Exceptions的话,会让客户程序员感到很不爽,因为你抛一个他就得接一个,就得处理一个。所以还不如定义返回值让他自己去做判断或直接抛Unchecked Exception。 如果你是一个应用程序员,就是说,你这一层已经基本上可以说是最后一层了,那么适当的使用Checked Exception可以很好的提高你的程序的可读性和可维护性。 那么,使用Checked Exception的原则是什么呢?用Bloch的话来说,就是 Use checked exceptions for recoverable conditions and run-time exceptions for programming errors 具体到Robbin讲的用户登陆的例子,登陆失败显然是recoverable的,不属于programming errors,所以我很同意Robbin的观点,即抛出一个LoginFailed Exception来处理这种情况。 至于Checked Exception的系统开销,不要担心,代码可读性和可维护性的提高带来的好处,是值得这些开销的。并且,你尽可以先优化其他不合理的地方,比如随处可见的new,尤其是循环里面的。 打个比方,你要省钱,最先要省的是不买五千块钱的皮鞋,八万块钱的领带,而不是每顿饭尽力省下五毛钱,对不对?
发表时间:
Java 理论与实践: 关于异常的争论 http://www-/developerWorks/cn/java/j-jtp05254/index.shtml http://www-/developerWorks/cn/java/j-jtp05254/index_eng.shtml
Rod Johnson 是 J2EE Design and Development (请参阅 参考资料) 的作者,这是我所读过的关于 Java 开发,J2EE 等方面的最好的书籍之一。他采取一个不太激进的方法。他列举了异常的多个类别,并且为每个类别确定一个策略。一些异常本质上是次要的返回代码(它通常指示违反业务规则),而一些异常则是“发生某种可怕错误”(例如数据库连接失败)的变种。Johnson 提倡对于第一种类别的异常(可选的返回代码)使用检查型异常,而对于后者使用运行时异常。在“发生某种可怕错误”的类别中,其动机是简单地认识到没有调用者能够有效地处理该异常,因此它也可能以各种方式沿着栈向上扩散而对于中间代码的影响保持最小(并且最小化异常淹没的可能性)。
我已经发现非检查型异常的最大风险之一就是它并没有按照检查型异常采用的方式那样自我文档化。除非 API 的创建者明确地文档化将要抛出的异常,否则调用者没有办法知道在他们的代码中将要捕获的异常是什么。
Johnson 建议在每个包的基础上选择检查型和非检查型异常。使用非检查型异常时还要记住,即使您并不捕获任何异常,也可能需要使用 try...finally 块,从而可以执行清除动作例如关闭数据库连接。对于检查型异常,我们有 try...catch 用来提示增加一个 finally 子句。对于非检查型异常,我们则没有这个支撑可以依靠。
robbin 发表时间:
使用Checked Exception还是UnChecked Exception的原则,我的看法是根据需求而定。 如果你希望强制你的类调用者来处理异常,那么就用Checked Exception; 如果你不希望强制你的类调用者来处理异常,就用UnChecked。 那么究竟强制还是不强制,权衡的依据在于从业务系统的逻辑规则来考虑,如果业务规则定义了调用者应该处理,那么就必须Checked,如果业务规则没有定义,就应该用UnChecked。 还是拿那个用户登陆的例子来说,可能产生的异常有: IOException (例如读取配置文件找不到) SQLException (例如连接数据库错误) ClassNotFoundException(找不到数据库驱动类) NoSuchUserException PasswordNotMatchException 以上3个异常是和业务逻辑无关的系统容错异常,所以应该转换为RuntimeException,不强制类调用者来处理;而下面两个异常是和业务逻辑相关的流程,从业务实现的角度来说,类调用者必须处理,所以要Checked,强迫调用者去处理。 在这里将用户验证和密码验证转化为方法返回值是一个非常糟糕的设计,不但不能够有效的标示业务逻辑的各种流程,而且失去了强制类调用者去处理的安全保障。 至于类调用者catch到NoSuchUserException和PasswordNotMatchException怎么处理,也要根据他自己具体的业务逻辑了。或者他有能力也应该处理,就自己处理掉了;或者他不关心这个异常,也不希望上面的类调用者关心,就转化为RuntimeException;或者他希望上面的类调用者处理,而不是自己处理,就转化为本层的异常继续往上抛出来。
发表时间:
《重构》这本书中关于正确使用 Exception 有两个重构方法: 310 页:Replace Error Code with Exception 315 页:Replace Exception with Test 当然,Martin Fowler 说的话并不是圣经,但是他的话是如此中肯以至于我很自然地会首先遵循他的指导。
发表时间:
异常类层次设计的不好带来的结果就是非常糟糕,例如JTA的异常类层次,例如EJB的异常类层次,但是也有设计的很好的,例如Spring DataAccessException类层次结构。 用设计糟糕的异常类层次来否定异常这个事物,是极度缺乏说服力的,就好像有人用菜刀砍了人,你不能否定这把菜刀一样。 这个帖子这么长了,该讨论的问题都讨论清楚了,总结也总结过n遍了,所以我早就没有兴趣再跟帖了。 实际上,这个讨论中隐含两个不断纠缠的话题: 1、checked ,还是unchecked异常? 2、用自定义的方法调用返回code,还是用异常来表达不期望各种的事件流 经过这么长的讨论,我认为结论已经非常清楚: 1、应该适用unchecked异常,也就是runtimeexception,这样可以让无法处理异常的应用代码简单忽略它,让更上层次的代码来处理 2、应该适用异常来表达不期望的各种事件流 事实上,你们去看一下现在Spring,Hibernate3都已经采用这种方式,特别是Spring的DataAccessException异常层次设计,是一个很好的例子。即使用RuntimeException来表达不期望的各种事件流。
sunflowers
浏览: 321373 次
来自: 上海
楼主厉害,现在可以使用了
楼主好牛逼
多谢楼主了
public void testImportInContex ...
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'

我要回帖

更多关于 x360ce报错exception 的文章

 

随机推荐