1、PMD(http://pmd.sourceforge.net/pmd-5.0.5/integrations.html#eclipse)
工作原理:
PMD是一种开源分析Java代码错误的工具。与其他分析工具不同的是,PMD通过静态分析获知代码错误。也就是说,在不运行Java程序的情况下报告错误。PMD附带了许多可以直接使用的规则,利用这些规则可以找出Java源程序的许多问题,例如:
® 潜在的bug:空的try/catch/finally/switch语句
® 未使用的代码:未使用的局部变量、参数、私有方法等
® 可选的代码:String/StringBuffer的滥用
® 复杂的表达式:不必须的if语句、可以使用while循环完成的for循环
® 重复的代码:拷贝/粘贴代码意味着拷贝/粘贴bugs
® 循环体创建新对象:尽量不要再for或while循环体内实例化一个新对象
@ 资源关闭:Connect,Result,Statement等使用之后确保关闭掉
此外,用户还可以自己定义规则,检查Java代码是否符合某些特定的编码规范。例如,你可以编写一个规则,要求PMD找出所有创建Thread和Socket对象的操作。
安装组件到eclipse或myeclipse:
To install the PMD plugin for Eclipse:
- Start Eclipse and open a project
- Select "Help"->"Software Updates"->"Find and Install"
- Click "Next", then click "New remote site"
- Enter "PMD" into the Name field and http://sourceforge.net/projects/pmd/files/pmd-eclipse/update-site/ into the URL field
- Click through the rest of the dialog boxes to install the plugin
Alternatively, you can download the latest zip file and follow the above proceduresexcept for using "New local site" and browsing to the downloaded zip file.
To configure PMD, select "Windows"->"Preferences", then select PMD.
To run PMD, right-click on a project node and select "PMD"->"Check code with PMD".
To run the duplicate code detector, right-click on a project node and select "PMD"->"Find suspect cut and paste". The report will be placed in a "reports" directory in a file called "cpd-report.txt".
To find additional help for other features, please read included help by selectingHelp->Help Contents and browse the "How to..." section in the "PMD Plugin Documentation" book.
After installing an update, if you get an Exception such as "java.lang.RuntimeException: Couldn't find that class xxxxx",try deleting the ruleset.xml file in the .metadata/plugins/net.sourceforge.pmd.eclipse directory in your workspace.
To get Eclipse to not flag the @SuppressWarnings("PMD") annotation, look under the menu headings Java -> Compiler -> Errors/Warnings -> Annotations -> Unhandled Warning Token.
2、CheckStyle(http://sourceforge.net/projects/eclipse-cs/?source=directory)
它能够自动化检查代码规范,CheckStyle默认提供一下主要检查内容:
·Javadoc注释
·命名约定
·标题
·Import语句
·体积大小
·空白
·修饰符
·块
·代码问题
·类设计
·混合检查(包活一些有用的比如非必须的System.out和printstackTrace)
安装步骤:
从http://sourceforge.net/projects/eclipse-cs/?source=directory下载zip包,在eclipse的help里,选择“software updates”增加插件——add archive,按照指示增加checkstyle,最后重启eclipse。重启后右击菜单看到“checkstyle”表明增加成功。
成功加入插件后,可以按照项目的需要,定制代码规范的规则文件:checkstyle.xml(文件名自定义)
右击项目——》properties——》checkstyle——》Local check configuration,在Local check configuration加入规则xml文件,具体操作如下:
checkstyle.xml文件内容可以在Local check configuration界面,选定好xml文件后,点击configure定制,也可以自己手动编辑xml文件增加规则。根据团队建设的代码规范,编辑出下面代码规则。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.3//EN" "http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
<!--
Checkstyle-Configuration: checkstyle
Description: none
-->
<module name="Checker">
<property name="severity" value="error"/>
<property name="charset" value="UTF-8"/>
<message key="general.fileNotFound" value="文件没找到!"/>
<message key="general.exception" value="有一个异常 - {0}"/>
<module name="TreeWalker">
<property name="severity" value="error"/>
<property name="tabWidth" value="4"/>
<message key="general.exception" value="有一个异常 - {0}"/>
<!-- 检查所有class和interface的javadoc -->
<module name="JavadocType">
<property name="authorFormat" value="\S"/>
<message key="type.missingTag" value="注解缺少 {0} tag."/>
<message key="javadoc.missing" value="缺少注解"/>
<message key="javadoc.unusedTagGeneral" value="不使用的注解tag"/>
<message key="type.tagFormat" value="注解tag {0} 必须符合正则表达式 ''{1}''."/>
</module>
<!-- 检查变量的javadoc -->
<module name="JavadocVariable"/>
<!-- 检查方法的javadoc -->
<module name="JavadocMethod">
<property name="suppressLoadErrors" value="true"/>
</module>
<!-- 命名的检查 -->
<!-- 包名的检查 -->
<module name="PackageName">
<property name="format" value="^[a-z]+(\.[a-z][a-z0-9]*)*$"/>
<message key="name.invalidPattern" value="包名 ''{0}'' 必须符合正则表达式 ''{1}''."/>
</module>
<!-- 包名的检查 -->
<module name="TypeName">
<message key="name.invalidPattern" value="名称 ''{0}'' 必须符合正则表达式 ''{1}''."/>
</module>
<!-- 方法名的检查 -->
<module name="MethodName">
<property name="severity" value="warning"/>
<property name="format" value="(^[a-z][a-zA-Z0-9]{0,14}$)"/>
<message key="name.invalidPattern" value="名称 ''{0}''必须符合以下正则表达式 ''{1}''."/>
<message key="method.name.equals.class.name" value="名称 ''{0}'' 不能与内部类名称相同."/>
</module>
<!-- 变量的检查 -->
<module name="MemberName">
<message key="name.invalidPattern" value="名称 ''{0}'' 必须符合正则表达式 ''{1}''."/>
</module>
<!-- 方法参数名的检查 -->
<module name="ParameterName">
<message key="name.invalidPattern" value="名称 ''{0}'' 必须符合正则表达式 ''{1}''."/>
</module>
<!-- 常量的检查 -->
<module name="ConstantName">
<message key="name.invalidPattern" value="名称 ''{0}'' 必须符合正则表达式 ''{1}''."/>
</module>
<!-- 长度的检查 -->
<!-- 每行不能超过120个字符 -->
<module name="LineLength">
<property name="max" value="120"/>
<message key="maxLineLen" value="行字符数超过 {0,number,integer} 个."/>
</module>
<!-- 每个方法长度不能超过50行 -->
<module name="MethodLength">
<property name="max" value="50"/>
<property name="tokens" value="METHOD_DEF"/>
<message key="maxLen.method" value="方法长度 {0,number,integer} 行 (最大允许行数为 {1,number,integer})."/>
</module>
<!-- 文件长度不能1500行 -->
<module name="FileLength">
<property name="severity" value="warning"/>
<property name="max" value="1500"/>
<message key="maxLen.file" value="文件 {0,number,integer} 行 (最大行数为: {1,number,integer})."/>
</module>
<!-- 方法参数最多不能超过5个 -->
<module name="ParameterNumber">
<property name="severity" value="warning"/>
<property name="max" value="5"/>
<property name="tokens" value="METHOD_DEF"/>
<message key="maxParam" value="超过 {0,number,integer} 参数."/>
</module>
<!-- 多余的关键字如:interface里声明的变量和方法均是默认public的,故无需再定义public -->
<module name="RedundantModifier">
<message key="redundantModifier" value="冗余 ''{0}'' 修饰符."/>
</module>
<!-- 对区域的检查 -->
<!-- 不能出现空白区域 -->
<module name="EmptyBlock"/>
<!-- 所有区域要使用大括号 -->
<module name="NeedBraces">
<message key="needBraces" value="''{0}'' 结构必须要用大括号 '''{}'''s."/>
</module>
<!-- 多余的括号 -->
<module name="AvoidNestedBlocks">
<property name="severity" value="warning"/>
<property name="allowInSwitchCase" value="true"/>
<message key="block.nested" value="多余括号"/>
</module>
<!-- 代码的检查 -->
<!-- 不能出现空语句 -->
<module name="EmptyStatement">
<message key="empty.statement" value="空代码块."/>
</module>
<!-- 多余的throws -->
<module name="RedundantThrows">
<property name="severity" value="warning"/>
<message key="redundant.throws.classInfo" value="没办法获得类信息 {0}."/>
<message key="redundant.throws.duplicate" value="冗余的 throws: ''{0}'' 使用了多次."/>
<message key="redundant.throws.subclass" value="冗余的 throws: ''{0}'' 是 ''{1}''的子类."/>
<message key="redundant.throws.unchecked" value="冗余的 throws: ''{0}'' 是运行时的异常."/>
<metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="warning"/>
</module>
<!-- 同一行代码里不能声明多个变量 -->
<module name="MultipleVariableDeclarations">
<property name="severity" value="warning"/>
<message key="multiple.variable.declarations.comma" value="每一个变量的定义必须在它的声明处,且在同一行."/>
<message key="multiple.variable.declarations" value="每一行只能定义一个变量."/>
<metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="warning"/>
</module>
<!-- 定义常量必须使用大写字母 -->
<module name="UpperEll">
<message key="upperEll" value="必须使用大写字母 ''L''."/>
</module>
<!-- 定义数组必须使用java tyle:String[] args(c tyle:String args[]) -->
<module name="ArrayTypeStyle">
<message key="array.type.style" value="数组中括号位置不对,建议如:String[] args."/>
</module>
<!-- 不能出现魔法数 即不能直接使用1、2这种阿拉伯数字赋值,应将其赋予常量后再进行赋值 -->
<module name="MagicNumber">
<property name="severity" value="warning"/>
<message key="magic.number" value="''{0}'' 是一个魔法数(即常数)."/>
<metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="warning"/>
</module>
<!-- 循环语句里的条件声明的变量不能在语句块里被修改 -->
<module name="ModifiedControlVariable"/>
<!-- 导入无用的包 -->
<module name="UnusedImports">
<message key="import.unused" value="没被使用过 import - {0}."/>
</module>
<!-- 函数定义、变量定义、数据列表不能有空白符,但可以换行 -->
<module name="MethodParamPad">
<property name="allowLineBreaks" value="true"/>
</module>
<!-- 检查的修饰符顺序是否符合 Java 语言规范 :
1、public
2、protected
3、private
4、abstract
5、static
6、final
7、transient
8、volatile
9、synchronized
10、native
11、strictfp
-->
<module name="ModifierOrder">
<message key="mod.order" value="''{0}'' 修饰符没有按照 JLS 的建议顺序."/>
<message key="annotation.order" value="''{0}'' 注释修饰符不能在非注释修饰符前面."/>
</module>
<!-- if最多嵌套2层 -->
<module name="NestedIfDepth">
<property name="severity" value="warning"/>
<property name="max" value="2"/>
<message key="nested.if.depth" value="if-else嵌套语句个数为 {0,number,integer} (最大允许嵌套语句个数为: {1,number,integer})."/>
<metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="warning"/>
</module>
<!-- try最多嵌套2层 -->
<module name="NestedTryDepth">
<property name="max" value="2"/>
</module>
<!-- clone方法必须调用了super.clone() -->
<module name="SuperClone">
<message key="missing.super.call" value="方法 ''{0}'' 需要调用 ''super.{0}''."/>
</module>
<!-- finalize方法必须调用了super.finalize() -->
<module name="SuperFinalize">
<message key="missing.super.call" value="方法 ''{0}'' 需要调用 ''super.{0}''."/>
</module>
<!-- 不catch java.lang.Exception 即不能出现catch(Exception e)这种代码-->
<module name="IllegalCatch">
<property name="illegalClassNames" value="java.lang.Exception"/>
<message key="illegal.catch" value="Catching ''{0}'' 是不允许的."/>
</module>
<!-- 声明调用的类不在导入的包内 -->
<module name="PackageDeclaration">
<message key="missing.package.declaration" value="缺少包的定义."/>
<message key="package.dir.mismatch" value="包定义与目录名不匹配 ''{0}''."/>
</module>
<!-- 函数返回的个数最多不能超过3个 -->
<module name="ReturnCount">
<property name="severity" value="warning"/>
<property name="max" value="3"/>
<property name="format" value="^$"/>
<message key="return.count" value="Return 个数 {0,number,integer} (最大允许个数为: {1,number,integer})."/>
<metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="warning"/>
</module>
<!-- 方法的参数不能赋值 -->
<module name="ParameterAssignment">
<message key="parameter.assignment" value="参数赋值 ''{0}'' 是不允许的."/>
</module>
<!-- 导入不合法的包 -->
<module name="IllegalImport"/>
<!-- 检查方法是否存在单元测试junit的核心代码 -->
<module name="JUnitTestCase"/>
<!-- 禁止出现System.out.println -->
<module name="Regexp">
<property name="format" value="System\.out\.println"/>
<property name="ignoreComments" value="true"/>
</module>
</module>
<!-- 检查class里的代码是否出现重复代码 -->
<module name="StrictDuplicateCode">
<property name="min" value="100"/>
<message key="duplicates.lines" value="从第 {2}开始,有{0}行相同代码 与 {1}中重复."/>
</module>
<!-- 检查翻译文件 -->
<module name="Translation">
<message key="translation.missingKey" value="关键字 ''{0}'' 没找到."/>
</module>
</module>
最后,在main里:
checkstyle检查出的常见问题以及解决方法查看这个:http://hi.baidu.com/miyuehu/item/e02cec86f79723cbb0715459