月度归档:2013年12月

2013年度总结

一直以来有个习惯,看完一部电影、听完一张音乐专辑或者读完一本书,会去豆瓣上记录一下,方便总结这一年的业余生活。于是很容易整理出2013年的年度总结:

一、 电影

今年看过的电影有104部。有的电影,比如一些超级英雄电影『钢铁侠』系列、『美国队长』等,又比如一些坐影院中观看的电影『云图』,『致青春』等,刚看完时热血沸腾,可是时间久了回头再看,发现也不过如此。另外一些入的了电影历史殿堂的瑰宝之作,比如『2001太空漫游』,『奇爱博士』,『断背山』等,虽然得到了一片片的赞誉,但某些方面,或趣味性、或价值观,与个人喜好有些冲突,因此不甚喜欢。总之一句话,一部电影“好看”与否完全是个人的主观行为。

个人今年看过的最“好看”电影Top10:
1. 弗兰克·德拉邦特 - 『迷雾』
2. 雷德利·斯科特 等 - 『异形』系列(包括『异形1、2、3、4』,『普罗米修斯』)
3. 金成洙 - 『流感』
4. 阿方索·卡隆 - 『地心引力』
5. 迈克·尼科尔斯 - 『毕业生』
6. 詹姆斯·麦克特格 - 『V字仇杀队』
7. 瑞奇·摩尔 - 『无敌破坏王』
8. 吴宇森 - 『变脸』
9. 伊恩·索夫特雷 - 『万能钥匙』
10. 汤姆·提克威 - 『香水』

二、音乐

今年听过的音乐专辑有111张。今年以前,听过最多的歌曲是港台流行,终于听腻了情情爱爱,你侬我侬的声音。这一年里,听了一些华语摇滚,倍感清新。有些专辑几首单曲不错,但是剩余质量一般,比如Adele的『21』,比如李志,汪峰,罗大佑的一些专辑,另外有些专辑名声在外,但是个人不懂欣赏,比如枪花的『Appetite For Destruction』,林强的『向前走』等。在我的定义里,一张专辑是否出众,最低标准是专辑中40%的曲目好听,这个好听可以是旋律优美,也可以是歌词动人。

个人今年听过的最“好听”专辑Top10:
1. 李志 - 『梵高先生』
2. 逃跑计划 - 『世界』
3. 李志 - 『被禁忌的游戏』
4. 左小祖咒 - 『我不能悲伤地坐在你身旁』
5. Nightwish - 『Made in Hong Kong (and in Various Other Places)』
6. 刺猬 - 『白日梦蓝』
7. 汪峰 - 『花火』
8. Keane - 『Under The Iron Sea』
9. 痛苦的信仰 - 『不要停止我的音乐』
10. 罗大佑 - 『之乎者也』

三、 阅读

今年看过的书有27本,阅读量较去年下降较为明显。主要是今年有很大一部分时间在看Erlang编程,另外下半年的工作也确实很忙。

个人今年看过的最佳图书Top10:
1. Joe Armstrong - 『Erlang程序设计』
2. 斯蒂芬·霍金 - 『大设计』
3. 徐中约 - 『中国近代史(上册)』
4. 保罗·福塞尔 - 『格调』
5. Scott Chacon - 『Pro Git』
6. Craig Walls - 『Spring in Action(第3版)』
7. David Gourley, Brian Totty - 『HTTP权威指南』
8. 道格拉斯·亚当斯 - 『银河系搭车客指南』
9. 蒋勋 - 『孤独六讲』
10. 方舟子 - 『批评中医』

--EOF--

Vim必知必会:初阶

以前我对待Vim的态度不是很友好,因为它的学习曲线实在太陡,并认为其早就应该被更加现代化的文本编辑器取代。直到工作以后,接触了越来越多的服务器端运维操作,无论修改配置文件还是查询日志,没有Vim已经寸步难行,于是渐渐也就适应了。

本系列文章只讲究实用性,所有操作均来自于平日的实践总结,不罗列那些边边角角、充满秀技意味的命令。此为第一篇,关于Vim的初阶用法,熟记下列命令并熟练应用,就已经可以在Vim的江湖里存活了。

1. 移动光标

移动光标可以用hjkl键和左、下、上、右方向键,两者的作用一样,区别在于,hjkl只适用于普通模式下的操作,而方向键适用于各种模式(包括插入模式、命令模式等)。

2. 自由编辑文本

iIaAoO键可以使Vim进入插入模式,它们的区别在于插入位置不同:

* i: 在光标所在位置前插入。
* I (Shift + i): 在当前行首插入。
* a: 在光标所在位置后插入。
* A (Shift + a): 在当前行尾插入。
* o: 在下一行行首插入。
* O (Shift + o): 在上一行行首插入。

插入完毕后,按ESC键回到普通模式。

3. 保存&退出

普通模式下,按 : 进入命令模式:

* w: 保存。
* w!: 强制保存(比如修改只读文件)。
* q: 退出。
* q!: 忽略未保存修改,强制退出。
* wq: 保存后退出。
* wq!: 强制保存后退出。

4. 删除

在普通模式下,
* x: 删除光标所在处字符。
* dd: 删除当前行。

在插入模式下,
* 退格键(backspace): 删除字符。

5. 快速移动

* gg: 快速移动到文件开头。
* G (Shift + g): 快速移动到文件末尾。
* 0: 快速移动到当前行首。
* $: 快速移动到当前行尾。替代方式:按A进入行尾插入模式,再按ESC退出插入模式。
* Ctrl + f: 向前翻一页。
* Ctrl + b: 向后翻一页。
* w: 移动到下一个单词的首字母,符号、标点也算作一个单词。(可用e替代,移动到下一个单词的尾字母)
* b: 移动到上一个单词的首字母,符号、标点也算作一个单词。

6. 撤销/重做

* u: 撤销上次修改操作。
* Ctrl + r: 重做上次被撤销的操作。

7. 搜索

* /word: 向下搜索关键词word。
* ?word: 向上搜索关键词word。
* n: 跳到下一个搜索关键词匹配处。如果是/word搜索,n跳向文件末尾方向,如果是?word搜索,n跳向文件开头方向。
* N: 跳到上一个搜索关键词匹配处。如果是/word搜索,N跳向文件开头方向,如果是?word搜索,N跳向文件末尾方向。

8. 简单替换

:进入命令模式,

* %s/src_chars/dest_chars/g: 全局替换,将src_chars替换为dest_chars。同1,$s/src_chars/dest_chars/g
* N1,N2s/src_chars/dest_chars/g: 指定区域替换,将第N1行到第N2行(含N1,N2)之间的src_chars替换为dest_chars。

9. 复制/粘贴

按行复制:
* yy: 复制当前行。
* Nyy: 从当前行开始,复制N行。

自由复制
* v: 开始选择字符。
* y: 复制已选择的字符。

粘贴:
* p: 在下一行粘贴已复制内容。

10. 自定义Vim样式

自定义几个常用的样式配置,编辑~/.vimrc:

1
2
3
4
5
6
" 开启语法高亮
syntax enable
" 显示行号
set number
" 开启搜索关键词高亮
set hls

--EOF--

Java Unchecked Exception

Java中java.lang.Throwable类是一切异常的基类,它有两种类型(子类):Error类和Exception类。Error类通常表示系统级别异常,如IOError,OutOfMemeryError等。Exception类则表示应用级别中出现的异常,如IOException,NullPointerException等。这种分类是简单的按异常来源进行划分的。

然而,要知道Java支持异常机制的根本原因是为了提高程序的健壮性,因为程序受运行环境等因素影响,在运行过程中出现异常不可避免,如果编程人员能事先采取措施,当异常情况出现时让程序能继续运行下去,或者能从异常中恢复,那么对软件的鲁棒性提升很大。所以,关于异常一个更好的分类方式是分为检查型异常(Checked Exception)和非检查型异常(Unchecked Exception)。

所谓检查型异常,就是编译器要求此类异常必需被try…catch…语句包围进行异常处理,它所隐含的意思是编程人员必需知道此次方法调用过程中可能出现的异常,并提前对其进行处理,所以一般检查型异常用在一些能使程序从异常中恢复的场景,比如IOException,可能重试就能解决问题。检查型异常一般都继承自java.lang.Exception,当然Exception本身也是检查型异常。另一类是非检查型异常,这类异常的使用场景是程序无法从该异常中恢复,前文提到的Error类及其子类都属于此类异常,因为出现系统(底层)级别的错误后,程序不大可能还能恢复正常,例如OutOfMemeryError堆内存满。还有一类非检查型异常是RuntimeException类及其子类,它们所代表的是应用级别中出现的无法恢复的运行时异常,例如NullPointerException空指针异常,ArrayIndexOutOfBoundsException数组越界异常等。对应到Java的异常体系中,两种异常分别为:

1. 非检查型异常:java.lang.Error类及其子类,java.lang.RuntimeException类及其子类。
2. 检查型异常:java.lang.Exception类及其所有除java.lang.RuntimeException类(包括其子类)外的所有子类。

从编程角度来看,两者的最大区别是非检查型异常无需进行try…catch…语句包围,而检查型异常一定需要try…catch…语句包围。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public void unchecked() throws RuntimeException {
}
 
public void checked() throws Exception {
}
 
public void test() {
    unchecked();
    try {
        checked();
    } catch (Exception e) {
    }
 
}

通常来说,检查型异常和非检查型异常的使用场景为:如果经过处理后程序能从异常中恢复,那么使用检查型异常,给编程人员一个机会进行异常处理;否则,使用非检查型异常。

这里还有两个新手存疑的问题:

1. 为什么Java编译器只要求检查型异常有try…catch…语句包围处理,而对非检查型异常则无此约束?
这是从程序的优雅性上考虑的,Java程序中充满了各种各样潜在的非检查型异常,如果都要用try…catch…语句处理异常,那么写出来的程序是庞大而冗余的。要知道即使连最简单的除法程序:

1
2
3
int foo(Integer a, Integer b) {
    return a / b;
}

可能也会存在NullPointerException,ArithmeticException,以及其他潜在的系统级Error异常。

当然,也不能为了使程序简洁而偷懒将一些本该是抛出检查型异常的方法改为抛出非检查型异常,这种编程行为完全浪费了Java设计人员的心血,影响程序健壮性。

另外,编译器虽然没有强制要求程序中捕捉非检查型异常,但是有时候对非检查型异常进行捕捉也有好处,例如Web项目中对数据库驱动抛出的SQLException进行捕捉能避免用户看到恼人的异常堆栈信息。

2. 是否所有异常都能捕捉?
可以。前文说过,java.lang.Throwable类是Java中所有异常的基类,要想程序万无一失(通常无此必要),只需捕捉Throwable异常即可:

1
2
3
4
5
6
void bar() {
    try {
        doAnyThing();
    } catch (Throwable t) {
  }
}

--EOF--