8种常见的Java不规范代码

tsl0922 发布于 2012/09/17 11:48
阅读 25K+
收藏 194
在工作上,我最近对一个现有的Java项目代码进行了清理。完成之后,我发现了一些反复出现的不规范代码。所以,我把它们整理成了一个列表出来分享给我的同行希望能引起注意并改善代码的质量和可维护性。
这个列表不区分顺序,全部来自一些代码质量检查工具,如 CheckStyle, FindBugsPMD

在Eclipse中格式化源代码并管理import语句
Eclipse提供了自动格式化源代码和管理import语句的功能(并移除未使用的语句)。你可以使用下面的快捷键来使用这些功能。
  • Ctrl + Shift + F – 格式化源代码。
  • Ctrl + Shift + O – 管理import语句并移除未使用的语句。
除了手动执行这两个功能外,你还可以让Eclipse在保存文件的时候自动格式化源代码并自动管理import语句。要做到这个,在Eclipse中,到 Window -> Preferences -> Java -> Editor -> Save Actions并启用 Perform the selected actions on save,选中 Format source codeorganize imports

避免在方法中出现多个return语句(退出点):
在你的方法中,确保只有一个 退出点。不要在一个方法中使用多于一个return语句。

如,下面的代码是 不推荐的,因为它有多个退出点(return语句)。
private boolean isEligible(int age){
  if(age > 18){
    return true;
  }else{
    return false;
  }
}

上面的代码可以这么写(当然,下面的代码还可以改进,后面再说)。
private boolean isEligible(int age){
  boolean result;
  if(age > 18){
    result = true;
  }else{
    result = false;
  }
  return result;
}

简化if-else方法:
我们写了一些只要一个参数的工具方法,检查一些条件并根据条件返回一个值。如,在上面见到的 isEligible方法。
private boolean isEligible(int age){
  boolean result;
  if(age > 18){
    result = true;
  }else{
    result = false;
  }
  return result;
}

可以只使用一个return语句来重写此方法。
private boolean isEligible(int age){
  return age > 18;
}

不要为Boolean,Integer或String创建新的实例:
避免创建新的Boolean,Integer,String等实例。使用Boolean.valueOf(true)代替new Boolean(true)。两种写法效果差不多但却可以改善性能。

在代码块周围使用大括号:
永远不要忘记在块类型语句(如:if,for,while)周围使用大括号。这可以减少代码歧义并且避免在你修改代码块的时候产生新的bug。
不推荐
if(age > 18)
  return true;
else
  return false;

推荐
if(age > 18){
  return true;
}else{
  return false;
}

把方法的参数声明为final类型:
总是在所有兼容的地方把把方法的参数声明为final。这样做的话,当你无意中修改了参数的值,编译时会得到警告,并且编译生成的字节码也会得到优化。
推荐
private boolean isEligible(final int age){ ... }

用大写命名public static final类型成员变量:
总是使用大写命名用public static final类型变量。这样可以让你很容易区分常量和本地变量。
不推荐
public static final String testAccountNo = "12345678";

推荐
public static final String TEST_ACCOUNT_NO = "12345678";

把多个if语句合并成一个:
下面的代码
if(age > 18){
  if( voted == false){
    // eligible to vote.
  }
}

可以使用一个if语句改写为:
if(age > 18 && !voted){
  // eligible to vote
}

别忘了给switch添加default语句:
总是给switch添加一个default语句。

避免 重复 使用同样的字符串,创建一个常量吧:
如果你需要在多个地方使用同一个字符串,那就创建一个字符串常量来使用吧。
下面的代码:
private void someMethod(){
  logger.log("My Application" + e);
  ....
  ....
  logger.log("My Application" + f);
}

可以创建一个常量代替字符串"My Application":
public static final String MY_APP = "My Application";

private void someMethod(){
  logger.log(MY_APP + e);
  ....
  ....
  logger.log(MY_APP + f);
}

其它资源:Java最佳实践 , 代码规范检查 , PMD规则列表

原文链接,OSCHINA编译

加载中
0
东胜神洲
东胜神洲
避免在方法中出现多个return语句(退出点):
在你的方法中,确保只有一个 退出点。不要在一个方法中使用多于一个return语句。
------------------------------------------------------------------------------------------------
这一条在以前是非常强调的,但是要注意一点,现在的编程,更加强调的是“清晰和可读性”,对于单个出口(一个 return 语句),就要留意不要墨守成规。。。特别是多个  if-else 嵌套时,使用多 return 语句反而更好。。。详细情况,可以参考《重构》一书中的“Replace Nested Conditional with Guard Clauses”

核心与要旨:保持代码清晰与可读性才是关键 ,在这个前提下,才考虑是否使用单一或多个退出点。


hello++
hello++
当业务逻辑内if判断层数增加到10层,20层......的时候,第一条的推荐会导致代码没法阅读的。
劉頤林
我也支持。原则不是绝对的。
赵文亮
赵文亮
看来第一条争议性很大啊,那就根据实时情况决定吧。
徐林
徐林
多个退出点有时是必要的,特别是当逻辑比较复杂、嵌套比较多的时候。
warner
warner
顶,这要看具体情况而定,如果业务逻辑过于复杂时,用return更清晰一点
下一页
0
东胜神洲
东胜神洲
从代码可读性(易维护)角度来看, if-else 与 for 语句,通常是逻辑业务“藏污纳垢”的地方,常说的可读性差,难维护,就是这些地方包藏着太多东西造成。。。因为这个原因,针对这两种语言结构的“最佳实践”也比较多。。例如使用 switch 替代 if-else;使用多态替代 if-else;充分利用包容类库与闭包来处理 for 循环等等。。但是,毕竟说语境的差异,所采用的方法不一样,所以在运用这些“最佳实践”时,也要把握分寸。。盲目相信和使用,反而会适得其反效果。。
K
Kailunio
回复 @mystar : 有区别啊亲。switch对所有case生成了一个快速查找表,不似if else那种逐个判断,是效率上的提升啊。
谯洪敏
谯洪敏
回复 @mystar : 去掉了switch.我个人觉得switch更清晰可读性更高.javascript一直可以支持string类型的判断.Java7之前都不支持.还好java7增加了这个功能.让代码更漂亮.写起来更人性化了.
mystar
mystar
用 switch 替代 if-else 绝对不是什么好办法,和if-else没有本质区别,还更加难读,容易陷入技巧性错误,现在已经有些语言彻底去除了switch语法。
0
轻风抚翼
轻风抚翼

引用来自“delphixp”的答案

避免在方法中出现多个return语句(退出点):
在你的方法中,确保只有一个 退出点。不要在一个方法中使用多于一个return语句。
------------------------------------------------------------------------------------------------
这一条在以前是非常强调的,但是要注意一点,现在的编程,更加强调的是“清晰和可读性”,对于单个出口(一个 return 语句),就要留意不要墨守成规。。。特别是多个  if-else 嵌套时,使用多 return 语句反而更好。。。详细情况,可以参考《重构》一书中的“Replace Nested Conditional with Guard Clauses”

核心与要旨:保持代码清晰与可读性才是关键 ,在这个前提下,才考虑是否使用单一或多个退出点。


代码 规范的初衷是为了提高代码可读性和可维性,不能一味死用,还需灵活使用。要不然就远离 代码 规范初衷了
0
铂金小鸟
铂金小鸟
不要为Boolean,Integer或String创建新的实例:
避免创建新的Boolean,Integer,String等实例。使用Boolean.valueOf(true)代替new Boolean(true)。两种写法效果差不多但却可以改善性能。

这个不敢苟同。通过查看jdk rt源码,可以发现。valueOf 内部也是 new 出来的。例如Integer 的是这样的

  /**
     * Returns an <code>Integer</code> object holding the
     * value of the specified <code>String</code>. The argument is
     * interpreted as representing a signed decimal integer, exactly
     * as if the argument were given to the {@link 
     * #parseInt(java.lang.String)} method. The result is an
     * <code>Integer</code> object that represents the integer value
     * specified by the string.
     * <p>
     * In other words, this method returns an <code>Integer</code>
     * object equal to the value of:
     *
     * <blockquote><code>
     * new Integer(Integer.parseInt(s))
     * </code></blockquote>
     *
     * @param      s   the string to be parsed.
     * @return      an <code>Integer</code> object holding the value
     *             represented by the string argument.
     * @exception   NumberFormatException  if the string cannot be parsed 
     *             as an integer.
     */
    public static Integer valueOf(String s) throws NumberFormatException
    {
	return new Integer(parseInt(s, 10));
    }


Lunar_Lin
Lunar_Lin
据我这个搞C++的人所知道的,java的Boolean似乎是不会创建新实例的把。。他就2种值。JVM底层不会优化吗?举的栗子不好。
xoHome
xoHome
你这个和文章讲述的环境不同,不能做对比。文章的意思应该是尽可能用基本数据类型,例如:在循环创建变量的环境中,对象和基本类型的性能差异非常大。
0
铂金便便
铂金便便
我发现我写的代码真是中规中矩啊。。。。
李嘉图
李嘉图
那是因为你是个普通人!呵呵。不过对我来说有些时候代码就是有废话,需要改!
0
明月照大江
明月照大江
是让电脑跑起来开心(在语句上进行性能优化),还是让程序员写得开心(为了可读性使用很多的技巧),取决于是机器的成本高还是程序员的成本高。
0
jungle323
jungle323
CSDN里的文章  写的是十大不规范
0
我是潮汐
我是潮汐
单个return 这个觉得没必要.多个return反而更直观.
0
铂金小鸟
铂金小鸟

引用来自“铂金小鸟”的答案

不要为Boolean,Integer或String创建新的实例:
避免创建新的Boolean,Integer,String等实例。使用Boolean.valueOf(true)代替new Boolean(true)。两种写法效果差不多但却可以改善性能。

这个不敢苟同。通过查看jdk rt源码,可以发现。valueOf 内部也是 new 出来的。例如Integer 的是这样的

  /**
     * Returns an <code>Integer</code> object holding the
     * value of the specified <code>String</code>. The argument is
     * interpreted as representing a signed decimal integer, exactly
     * as if the argument were given to the {@link 
     * #parseInt(java.lang.String)} method. The result is an
     * <code>Integer</code> object that represents the integer value
     * specified by the string.
     * <p>
     * In other words, this method returns an <code>Integer</code>
     * object equal to the value of:
     *
     * <blockquote><code>
     * new Integer(Integer.parseInt(s))
     * </code></blockquote>
     *
     * @param      s   the string to be parsed.
     * @return      an <code>Integer</code> object holding the value
     *             represented by the string argument.
     * @exception   NumberFormatException  if the string cannot be parsed 
     *             as an integer.
     */
    public static Integer valueOf(String s) throws NumberFormatException
    {
	return new Integer(parseInt(s, 10));
    }


回复 @xoHome  @Lunar_Lin :  单纯的Boolean的话,valueof是比重新new 快。但是
对于 String ,用ValueOf 和new String 一样的,不过ValueOf要多一次调用。如果这一次调用也影响那么一点性能的话那还是new String 效率高。
至于integer,用ValueOf肯定比直接new 效率差,看源码得知,valueof内部进行了判断,转换等等操作,然后才调用new Integer返回一个实例。
0
兔bug
兔bug
细节需要注意下!
返回顶部
顶部