1. 运行时异常和受检异常

2. 提前预防运行时异常。最常发生的是NPE,而检查NPE是程序员的基本职责。其他的,如除0等运行时异常的检查,需要程序员仔细检查,每个函数都得检查(除非可以确定不会有空指针等情况),哪怕if()语句数量增加。无法通过预检查的异常除外,如在解析一个外部传来的字符串形式数字时,通过catch NumberFormatException来实现。

null:1)如果是外部获取,则有必要检查null,也有必要进行有效性检查(validationCheck);2)如果是内部的或者逻辑上保证正确的,可以不查null。

3. 处理受检异常。如从数据库取数据,http链接等获取外部数据,必须进行受检异常处理,因为这是即时进行正常操作也可能出现异常的情况。

比较赞同的一段https://www.zhihu.com/question/35085136

所有的运行时异常都是可以在发生之前检测到并且避免的,这意味着一段代码如果写得好,将不会有抛出运行时异常的可能。因此,运行时异常被抛出时,程序员应该检查代码中的bug,而不是catch它。
从语言本身的角度讲,程序不该去catch这类异常,虽然能够从诸如RuntimeException这样的异常中catch并恢复,但是并不鼓励终端程序员这么做,因为完全没要必要。因为这类错误本身就是bug,应该被修复,出现此类错误时程序就应该立即停止执行。

我想,之所以区分出受检异常和非受检异常,是因为受检异常的发生不受自身代码控制,往往是在和外部连接的时候发生,也就是自身代码逻辑正确并不能阻止错误情况的发生;处理受检异常是在编译时检查,函数会抛出受检异常的原因是它认为自己无法处理这个异常,如果认为自己可以处理,则处理不再抛出。非受检异常大部分是由于程序逻辑欠缺导致的,抛出异常是为了定位错误发生的地点和原因;如果逻辑上考虑或检查的比较完备,则理论上不会发生非受检异常。

但是有的时候确实会担心、也会发生考虑不周全的时候,(因为出现的次数少,感觉也不适合直接中断运行),这时候,我觉得可以在比较外层的地方try catch runtimeException,记录错误,并找出原因修复,同时主程序继续运行。

       try {
Class12 class12 = new Class12(tradingDB);
class12.completeSummaryItems(summaryItems); Report report = new Report(tradingDB, calendar.getTime());
report.addSummaryItem(summaryItems); report.calculate();
report.writeDB();
} catch (RuntimeException e) {
LOGGER.error("internal error", e);
}

这个记录的目的是记录log,并且通过后台日志监控程序通知开发人员查看此bug,修复程序。如果直接崩溃,不一定会写入日志。

4. DB或连接类等基础类无需关心连接失效问题,由上层类或连接池关心。每一个模块或者类,都只需要关注自身应当具备的功能,超出的部分不应过多关心。久而久之,慢慢就成了面向对象咯(?)。

5. exception,交给调用者处理,如果认为所在层次应该处理此exception时,自己处理。

比如数据库连接类:


public class DB {
   public List<List<String>> select(String query) {
List<List<String>> res = new ArrayList<List<String>>();
Statement st = null;
ResultSet rs = null;
try {
st = dbConn.createStatement();
rs = st.executeQuery(query);
while (rs.next()) {
List<String> row = new ArrayList<String>();
for (int i = 1; i <= rs.getMetaData().getColumnCount(); i++) {
row.add(rs.getString(i));
}
res.add(row);
}
} catch (SQLException e) {
LOGGER.error("error while executing sql<" + query + ">.", e);
res = null;
} finally {
if (st != null) {
try {
st.close();
} catch (SQLException e) {
LOGGER.warn("close db statement failed.", e);
}
}
}
return res;
}
}

这个select函数自身处理了SQLException受检异常,是因为从程序整体上看,对于SQLException的处理为:写日志文件,并返回空集合。在select函数里是可以完成这一操作,且返回结果和抛出异常倒上一层的处理结果一致,那么就可以在这一层处理;另一方面在这一层处理,也可以避免抛出异常后,每次调用都要处理一下异常,减少修改量。

如果是在制作一个工具包,那么最好是抛出异常,由调用者处理(一般调用者也会像DB这个类一样做一个包装)。这里不是对外的工具包,所以不需要。

6. 准守api的约定很重要,包括自己编写api时,对约定的重视程度决定着api/代码的质量。如果约定不会返回null值,那么api就一定不要返回空值。如果返回null值是合理的,则说明返回的发生条件。

7. 如果在自身层次处理了exception,则返回值最好是可以让程序继续运行,但不会进一步处理数据的数值。比如:返回一个空的List,那么调用者接收到返回值后,不会中断程序,又由于返回的list个数为0,也不会往下一步运行。这一实现也需要程序整体上都是这么一个风格,即需要每一步都有对于空对象的处理。这样当exception发生后,调用者对数据的处理一视同仁,但是最后的结果能反映有错误发生。

8. 日志写入文件,信息要尽可能详细。不能太少,也不要重复。如果一个连接断开会导致不停的写日志,最好优化一下。

9. 日志格式需要统一,关键信息需写入日志文件。统一处理:日志监控程序,定时(半分钟)扫描一次日志,从上次读取的地方开始,发现有error字符串,则发邮件告警。

sub analyze {
my ($fh, $pos, $words) = @_;
my $lines = [];
seek($fh, , ); # move to the end of file
my $end = tell($fh);
if ($end <= $pos) {
## size of file is smaller than recorded value, the file must be modified
return ($lines, (($end<) ? : $end));
}
my $hasOneLine = ;
seek($fh, $pos, ); ## make file pointer points to the recorded position
my $cur = $end;
for(; my $line = readline($fh); $cur = tell($fh)) {
if($line =~ /$words/) {
$line =~ s/\n//;
if (!$hasOneLine) {
# only store one line
push(@$lines, $line);
$hasOneLine = ;
}
}
}
return ($lines, $cur);
}

对于通过crontab启动的程序,如果想要监控程序有没有正常启动,可以查看/var/log/cron日志,如果有新的启动记录,则正常。如果没有,那么可以到/var/spool/mail/root文件中查看原因(前提是crontab没有屏蔽错误信息)。这里的屏蔽错误信息指的是:

* * * * * $HOME/Workspace/monitor/admin/monitorReboot.pl >&  | cat >> $HOME/Workspace/monitor/admin/log

其中2>&1表示把错误信息流重定向,重定向则表示屏蔽了错误信息。如果把2>&1去掉:

* * * * * $HOME/Workspace/monitor/admin/monitorReboot.pl   | cat >> $HOME/Workspace/monitor/admin/log

则错误信息会记录在/var/spool/mail/root文件中。不过一般情况下,不用监控crontab,只要开始的时候人工确认一下执行了就行,linux系统还是值得信赖的。

ps. 对文件的操作需要注意inode的变化。有些软件如vim,在修改文件后会产生一个新的inode,需要特殊设置一下。

10. 日志的监控,如果需要高可靠性和实时性,可以考虑socket或 消息队列 等进程间通信方式。

11. 面向对象是一种思想,学习一种思想是一个长的过程。

java--何时处理Exception(哪一个层级),包装的基础类处理任务尽可能简洁,写入日志,检查null等运行时异常的更多相关文章

  1. java中exception和error有什么区别,运行时异常和一般异常有什么区别

    1.exception和error都是继承了throwable类,在java中只有throwable类型的实例才可以被抛出(throw)或者捕获(catch),它是异常处理机制的基本组成类型 2.ex ...

  2. Java中Error和Exception的异同以及运行时异常(Runtime exception)与检查型异常(checked exception)的区别

    一:Error和Exception的基本概念: 首先Exception和Error都是继承于Throwable 类,在 Java 中只有 Throwable 类型的实例才可以被抛出(throw)或者捕 ...

  3. java 检查抛出的异常是否是要捕获的检查性异常或运行时异常或错误

    /** * Return whether the given throwable is a checked exception: * that is, neither a RuntimeExcepti ...

  4. Java异常处理-----非运行时异常(受检异常)

    非运行时异常(受检异常) 如果出现了非运行时异常必须进行处理throw或者try{}catch(){}处理,否则编译器报错. 1:IOException 使用要导入包import java.io.IO ...

  5. Java软件工程师面试题:Java运行时异常与一般异常有什么不一样?

    异常表示程序运行过程中可能出现的非正常状态,运行时异常表示虚拟机的通常操作中可能遇到的异常,是一种常见运行错误.java编译器要求方法必须声明抛出可能发生的非运行时异常,但是并不要求必须声明抛出未被捕 ...

  6. Effective Java 第三版——70. 对可恢复条件使用检查异常,对编程错误使用运行时异常

    Tips 书中的源代码地址:https://github.com/jbloch/effective-java-3e-source-code 注意,书中的有些代码里方法是基于Java 9 API中的,所 ...

  7. Java中运行时异常和非运行时异常什么鬼?

    Java中的异常分类 RuntimeException(也称unchecked exceptions,运行时异常) 就是我们在开发中测试功能时程序终止,控制台出现的异常.(一般来说,出现运行时异常基本 ...

  8. Exception、Error、运行时异常与一般异常有何异同

    转自博客  https://blog.csdn.net/m0_37531231/article/details/79502778 一.开场白 对于程序运行过程中的可能出现异常情况,java语言使用一种 ...

  9. java运行时异常与一般异常有何异同?

    转自: http://blog.csdn.net/rainminism/article/details/51208572 Throwable是所有Java程序中错误处理的父类,有两种资类:Error和 ...

随机推荐

  1. C++名人的网站 转

    正如我们可以通过计算机历史上的重要人物了解计算机史的发展,C++相关人物的网站也可以使我们得到最有价值的参考与借鉴. 正如我们可以通过计算机历史上的重要人物了解计算机史的发展,C++相关人物的网站也可 ...

  2. HDU 3578 Greedy Tino(双塔DP)

    Greedy Tino Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Tota ...

  3. 六顶思维帽的思考,敏捷开发?——By Me

    人类的思维可以分为很多种,其中按照思维的深度和广度的侧重,可以分为纵向思维和横向思维两种: 简单的来说,“六顶思维帽”可以简单的理解为下图所示: 如何使用这种思维方式呢?举个例子:先输入一个待讨论的事 ...

  4. Hbase 学习笔记2----概念

    说在前面,本文部分内容来源于社区官网经过适度翻译,部分根据经验总结,部分是抄袭网络博文,(不一一列举引用,在此致歉)一并列在一起,本文的目的,希望能总结出一些有用的,应该注意到的东西,基本思路是先提出 ...

  5. 吴超老师课程--Hive的执行语句

    为什么选择Hive? (1)基于Hadoop的大数据的计算/扩展能力(2)支持SQL like查询语言(3)统一的元数据管理(4)简单编程 一:Hive的数据类型(1)基本数据类型tinyint/sm ...

  6. nginx缓存原理

    一.HTTP字段理解 1.Expires: 该字段的http1.0时的规范,值为一个绝对时间的GMT格式的时间字符串,代表缓存资源的过期时间,在这个时点之前即命中缓存. 缺点:服务器返回的时间,可能与 ...

  7. go——函数

    1.定义 函数是结构化编程的最小单元模式.它将复杂的算法过程分解为若干个较小任务,隐藏相关细节,使程序结构更加清晰,易于维护.函数被设计成相对独立,通过接收输入参数完成一段算法指令,输出或存储相关结果 ...

  8. 自己写的一个简单PHP采集器

    自己写的一个简单PHP采集器 <?php //**************************************************************** $url = &q ...

  9. SvsUtil.exe生成服务文件

    在程序中调用某个 WCF Services 一般按照如下步骤进行: 生成对应 Service 的代理类.程序创建该代理类实例,访问指定方法. 生成代理类 可通过在 Visual Studio 中针对某 ...

  10. 笔记——Springboot response、ServletOutputStream、图形验证码显示慢

    今天遇到一个图形验证码加载很慢的问题,大概耗时有200~500毫秒左右. 根据追踪,图形验证码图片生成耗时0~1毫秒,而response.getOutputStream.write()将图片写入前台页 ...