审查Java代码的十一种常见错误

代码审查是消灭Bug最重要的方法之一,这些审查在大多数时候都特别奏效。由于代码审查本身所针对的对象,就是俯瞰整个代码在测试过程中的问题和Bug。并且,代码审查对消除一些特别细节的错误大有裨益,尤其是那些能够容易在阅读代码的时候发现的错误,这些错误往往不容易通过机器上的测试识别出来。本文就常见的Java代码中容易出现的问题提出一些建设性建议,以便您在审查代码的过程中注意到这些常见的细节性错误。

通常给别人的工作挑错要比找自己的错容易些。别样视角的存在也解释了为什么作者需要编辑,而运动员需要教练的原因。不仅不应当拒绝别人的批评,我们应该欢迎别人来发现并指出我们的编程工作中的不足之处,我们会受益匪浅的。正规的代码审查(code inspection)是提高代码质量的最强大的技术之一,代码审查—由同事们寻找代码中的错误—所发现的错误与在测试中所发现的错误不同,因此两者的关系是互补的,而非竞争的。

如果审查者能够有意识地寻找特定的错误,而不是靠漫无目的的浏览代码来发现错误,那么代码审查的效果会事半功倍。在这篇文章中,我列出了11个Java编程中常见的错误。你可以把这些错误添加到你的代码审查的检查列表(checklist)中,这样在经过代码审查后,你可以确信你的代码中不再存在这类错误了。

一、常见错误1# :多次拷贝字符串

测试所不能发现的一个错误是生成不可变(immutable)对象的多份拷贝。不可变对象是不可改变的,因此不需要拷贝它。最常用的不可变对象是String。

如果你必须改变一个String对象的内容,你应该使用StringBuffer。下面的代码会正常工作:

String s = new String ("Text here");

但是,这段代码性能差,而且没有必要这么复杂。你还可以用以下的方式来重写上面的代码:

String temp = "Text here";
String s = new String (temp);

但是这段代码包含额外的String,并非完全必要。更好的代码为:

String s = "Text here";

二、常见错误2#: 没有克隆(clone)返回的对象

封装(encapsulation)是面向对象编程的重要概念。不幸的是,Java为不小心打破封装提供了方便——Java允许返回私有数据的引用(reference)。下面的代码揭示了这一点:

import java.awt.Dimension;
/***Example class.The x and y values should never*be negative.*/
public class Example{
  private Dimension d = new Dimension (0, 0);
  public Example (){ }
  /*** Set height and width. Both height and width must be nonnegative * or an exception is thrown.*/
  public synchronized void setValues (int height,int width) throws IllegalArgumentException{
   if (height < 0 || width < 0)
    throw new IllegalArgumentException();
    d.height = height;
   d.width = width;
  }
  public synchronized Dimension getValues(){
   // Ooops! Breaks encapsulation
   return d;
  }
}

Example类保证了它所存储的height和width值永远非负数,试图使用setValues()方法来设置负值会触发异常。不幸的是,由于getValues()返回d的引用,而不是d的拷贝,你可以编写如下的破坏性代码:

Example ex = new Example();
Dimension d = ex.getValues();
d.height = -5;
d.width = -10;

现在,Example对象拥有负值了!如果getValues() 的调用者永远也不设置返回的Dimension对象的width 和height值,那么仅凭测试是不可能检测到这类的错误。

不幸的是,随着时间的推移,客户代码可能会改变返回的Dimension对象的值,这个时候,追寻错误的根源是件枯燥且费时的事情,尤其是在多线程环境中。

更好的方式是让getValues()返回拷贝:

public synchronized Dimension getValues(){
return new Dimension (d.x, d.y);
}

现在,Example对象的内部状态就安全了。调用者可以根据需要改变它所得到的拷贝的状态,但是要修改Example对象的内部状态,必须通过setValues()才可以。

时间: 2024-09-19 08:59:08

审查Java代码的十一种常见错误的相关文章

Java枚举的七种常见用法总结(必看)_java

用法一:常量 在JDK1.5之前,我们定义常量都是:publicstaticfianl.....现在好了,有了枚举,可以把相关的常量分组到一个枚举类型里,而且枚举提供了比常量更多的方法. Java代码 public enum Color { RED, GREEN, BLANK, YELLOW } 用法二:switch JDK1.6之前的switch语句只支持int,char,enum类型,使用枚举,能让我们的代码可读性更强. Java代码 enum Signal { GREEN, YELLOW,

[Remoting FAQ]传递Remoting参数时遇到的两种常见错误

[Remoting FAQ] 传递Remoting参数时遇到的两种常见错误 Version Date Creator Description 1.0.0.1 2006-4-25 郑昀@Ultrapower 草稿   继续阅读之前,我们假设您熟悉以下知识: n         Remoting [现象1] 我们先来描述一个简单的错误.当你激活远端Remoting Objects时,却得到了这样的错误提示: 提示信息 Type 'Common.BTRequest' in Assembly 'Comm

java代码测试http协议505错误的解决方法

代码功能:通过java代码获取网页源代码: 所用工具:Myclipse8.5+tomcat6.0+浏览器 系统环境:windows xp旗舰版 火狐浏览器版本: IE浏览器版本:

避免Java EE项目评估中的常见错误

错误|项目 摘要: 软件开发项目评估是软件开发周期中关键又具备挑战性的一步,它是计划,进度,人员以及其他相关步骤的基础.项目低估会带来紧张的进度,高度压力的工作环境,未可预料的资源紧缺,低质量,项目实施延误等风险, 可以最大限度的破坏客户的生意以及公司的信誉:而另一方面,带有过多不合理泡沫的评估也会导致无效率的资源浪费以及引起客户和公司之间的不信任.评估企业Java项目因为技术的更新成了一个难题,本文通过几个方面透视提供了评估企业Java项目时应该考虑的问题 假如你是一个重要软件项目的项目经理,

数据科学初学者九种常见错误

更多深度文章,请关注:https://yq.aliyun.com/cloud 如果你想开始一个数据科学方面的职业,你可以通过避免这9个会使你付出高代价的初学者错误来免去几天,几个星期甚至几个月的挫折. 如果你不仔细,这些错误将会消耗你最宝贵的资源:你的时间.精力和动力. 我们将它们分为三类: 学习数据科学时的错误 求职时的错误 求职面试中的错误 学习数据科学时 第一组错误是"隐蔽的",很难发现.没有丝毫的预兆,它们如同温水煮青蛙般耗尽你的时间和精力,并且它们产生的误解围绕这个领域. 1

java开发中几种常见的线程池

线程池 java.util.concurrent:Class Executors 常用线程池 几种常用的的生成线程池的方法: newCachedThreadPool newFixedThreadPool newScheduledThreadPool newSingleThreadExecutor newSingleThreadScheduledExecutor 例子:newFixedThreadPool ExecutorService threadPool = Executors.newFixe

开母婴店的10种常见错误

NO.1轻易放弃一有挫折就想撤,一有因难就想放弃,动不动就龙飞凤舞的写:本店转让! NO.2不舍得做广告总觉得广告是无形的东西,花那些钱去做广告还不如多进点货实在. NO.3跟着感觉走从不记录有多少人进来:从不统计有多少人进来不买产品:从不观察竞争对手动静:从不考虑市场走向:最危险的就是这种店主,他无法寻找到问题的关键. NO.4不到黄河心不死,滞销商品舍不得亏本卖,一等再等,时装越久越不值钱,直到最后实在没人要当废品卖才会想:唉!早知道当初--记住,别不到黄河心不死,没几个人到了黄河还能游过去

多种负载均衡算法及其Java代码实现

首先给大家介绍下什么是负载均衡(来自百科) 负载均衡 建立在现有网络结构之上,它提供了一种廉价有效透明的方法扩展 网络设备和 服务器的带宽.增加 吞吐量.加强网络数据处理能力.提高网络的灵活性和可用性. 负载均衡,英文名称为Load Balance,其意思就是分摊到多个操作单元上进行执行,例如Web 服务器. FTP服务器. 企业关键应用服务器和其它关键任务服务器等,从而共同完成工作任务. 本文讲述的是"将外部发送来的请求均匀分配到对称结构中的某一台服务器上"的各种算法,并以Java代

Android 四种常见的线程池

引入线程池的好处 1)提升性能.创建和消耗对象费时费CPU资源 2)防止内存过度消耗.控制活动线程的数量,防止并发线程过多. 我们来看一下线程池的简单的构造 public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue, ThreadFactory threadFactory, RejectedExecution