设为首页收藏本站

LUPA开源社区

 找回密码
 注册
文章 帖子 博客
LUPA开源社区 首页 业界资讯 技术文摘 查看内容

10 个 Java 编码中微妙的最佳实践

2013-8-28 11:41| 发布者: 红黑魂| 查看: 3761| 评论: 0|来自: 开源中国编译

摘要:   这是10个最佳实践的列表,比你平时在Josh Bloch的《effective java》中看到的规则更加精妙。和Josh Bloch列出的非常容易学习的、和日常情况息息相关的实践相比,这个列表中提到了一些关于设计API/SPI的实践,虽 ...

3.避免使用匿名,局部或内部类

Swing程序员通常只要按几下快捷键即可生成成百上千的匿名类。在多数情况下,只要遵循接口、不违法SPI子

类型的生命周期(SPI subtype lifecycle),这样做也无妨。

但是不要因为一个简单的原因——它们会保存对外部类的引用,就频繁的使用匿名、局部或者内部类。因为无论

它们走到哪,外部类就得跟到哪。例如,在局部类的域外操作不当的话,那么整个对象图就会发生微妙的变化从

而可能引起内存泄露。

规则:在编写匿名、局部或内部类前请三思能否将它转化为静态的或普通的顶级类,从而避免方法将它们的对象

返回到更外层的域中。

注意:使用双层花括号来初始化简单对象:

1new HashMap() {{
2  put("1""a");
3  put("2""b");
4}}

这个方法利用了 JLS §8.6规范里描述的实例初始化方法(initializer)。表面上看起来不错,但实际上不提倡这种

做法。因为要是使用完全独立的HashMap对象,那么实例就不会一直保存着外部对象的引用。此外,这也会让

类加载器管理更多的类。


4. 现在就开始编写SAM!

Java8的脚步近了。伴随着Java8带来了lambda表达式,无论你是否喜欢。尽管你的API使用者可能会喜欢,

但是你最好确保他们可以尽可能经常的使用。因此除非你的API接收简单的“标量”类型,比如int、long、

String 、Date,否则让你的API尽可能经常的接收SAM。

什么是SAM?SAM是单一抽象方法[类型]。也称为函数接口,很快被注释为@FunctionalInterface。这与规

则2很配,EventListener实际上就是一个SAM。最好的SAM只有一个参数,因为这将会进一步简化lambda表

达式的编写。设想编写

1listeners.add(c -> System.out.println(c.message()));

替代

1listeners.add(new EventListener() {
2  @Override
3  public void message(MessageContext c) {
4    System.out.println(c.message()));
5  }
6});


设想以SAM的方式用jOOX处理XML:

1$(document)
2  // Find elements with an ID
3  .find(c -> $(c).id() != null)
4  // Find their child elements
5  .children(c -> $(c).tag().equals("order"))
6  // Print all matches
7  .each(c -> System.out.println($(c)))

规则:对你的API使用者好一点儿,从现在开始编写SAM/函数接口。

备注:有许多关于Java8 lambda表达式和改善的Collections API的有趣的博客:


5.避免让方法返回null

我曾写过1、2篇关于java NULLs的文章,也讲解过Java8中引入新的Optional类。从学术或实用的角

度来看,这些话题还是比较有趣的。

尽管现阶段Null和NullPointerException依然是Java的硬伤,但是你仍可以设计出不会出现任何问题的

API。在设计API时,应当尽可能的避免让方法返回null,因为你的用户可能会链式调用方法:

1initialise(someArgument).calculate(data).dispatch();


从上面代码中可看出,任何一个方法都不应返回null。实际上,在通常情况下使用null会被认为相当的异类。像  jQuery或 jOOX这样的库在可迭代的对象上已完全的摒弃了null。

Null通常用在延迟初始化中。在许多情况下,在不严重影响性能的条件下,延迟初始化也应该被避免。实际

上,如果涉及的数据结构过于庞大,那么就要慎用延迟初始化。

规则:无论何时方法都应避免返回null。null仅用来表示“未初始化”或“不存在”的语义。


6.设计API时永远不要返回空(null)数组或List

尽管在一些情况下方法返回值为null是可以的,但是绝不要返回空数组或空集合!请看 java.io.File.list()

方法,它是这样设计的: 

此方法会返回一个指定目录下所有文件或目录的字符串数组。如果目录为空(empty)那么返回的数组也为空
(empty)。如果指定的路径不存在或发生I/O错误,则返回null。

因此,这个方法通常要这样使用:

01File directory = // ...
02 
03if (directory.isDirectory()) {
04  String[] list = directory.list();
05 
06  if (list != null) {
07    for (String file : list) {
08      // ...
09    }
10  }
11}

大家觉得null检查有必要吗?大多数I/O操作会产生IOExceptions,但这个方法却只返回了null。Null是无

法存放I/O错误信息的。因此这样的设计,有以下3方面的不足:

  • Null无助于发现错误
  • Null无法表明I/O错误是由File实例所对应的路径不正确引起的
  • 每个人都可能会忘记判断null情况

以集合的思维来看待问题的话,那么空的(empty)的数组或集合就是对“不存在”的最佳实现。返回空(null)

数组或集合几乎是无任何实际意义的,除非用于延迟初始化。

规则:返回的数组或集合不应为null。



酷毙
1

雷人

鲜花

鸡蛋

漂亮

刚表态过的朋友 (1 人)

  • 快毕业了,没工作经验,
    找份工作好难啊?
    赶紧去人才芯片公司磨练吧!!

最新评论

关于LUPA|人才芯片工程|人才招聘|LUPA认证|LUPA教育|LUPA开源社区 ( 浙B2-20090187 浙公网安备 33010602006705号   

返回顶部