技术标签: jbuilder variables java string netbeans java基础技术 object
一、基础知识
PMD是一种分析Java代码错误的工具。与其他分析工具不同的是,PMD通过静态分析获知代码错误。也就是说,在不运行Java程序的情况下报告错误。PMD附带了许多可以直接使用的规则,利用这些规则可以找出Java源程序的许多问题,例如没有用到的变量、多余的变量创建操作、空的catch块,等等。此外,用户还可以自己定义规则,检查Java代码是否符合某些特定的编码规范。例如,你可以编写一个规则,要求PMD找出所有创建Thread和Socket对象的操作。
最初,PMD是为了支持Cougaar项目而开发的。Cougaar是美国国防高级研究计划局(Defense Advanced Research Projects Agency,DARPA)的一个项目。DARPA开放了PMD的源代码,所以PMD被发布到了SourceForge网站上。不久前,PMD的下载次数就超过了14000次,页面浏览次数超过了130000次。更重要的是,在源代码开放作者的努力下,越来越多的PMD规则和IDE插件被开发出来,然后加入到了PMD的核心项目之中。
你可以从PMD的网站下载PMD的二进制版本,或下载带源代码的版本,下载得到的都是ZIP文件。假设你下载了二进制版本,先把它解压缩到任意一个目录。接下来怎么做,就要看你准备怎么用它——最简单的,如果要在一个Java源代码目录中运行PMD,只需直接在命令行上运行下面的命令:
C:/data/pmd/pmd>java -jar lib/pmd-1.02.jar c:/j2sdk1.4.1_01/src/java/util text rulesets/unusedcode.xml |
输出结果类如:
c:/j2sdk1.4.1_01/src/java/util/AbstractMap.java 650 Avoid unused local variables such as 'v' c:/j2sdk1.4.1_01/src/java/util/Date.java 438 Avoid unused local variables such as 'millis' |
除了直接在命令行上运行PMD之外,还可以通过Ant、Maven或者各种集成开发环境(IDE)运行PMD,例如jEdit、Netbeans、Eclipse、Emacs、IDEAJ和JBuilder等。
二、内建规则
PMD本身就附带了许多规则。下面是几个例子。
没有用到的代码显然是应该被清除的。 public class Foo { // 下面这个实例变量没有用到 private List bar = new ArrayList(500); } 如果用一个接口也能达到同样的目标,为什么要返回一个具体的类?例如,下例可以改用List接口。 public ArrayList getList() { return new ArrayList(); } 当if的条件为真时,if代码块其实不做任何事情。下面这段代码其实可以写得更加简洁一些。 public void doSomething(int y) { if (y >= 2) { } else { System.out.println("Less than two"); } } 为什么要创建一个新的String对象?只要改用String x="x"就可以了。 String x = new String("x"); |
PMD还包含其他许多内建规则,但从上面几个例子已经可以看出PMD的基本工作方式。只要定义适当的静态规则,PMD就可以象一个富有经验的程序员那样,帮你指出代码存在的问题。
三、工作原理
PMD的核心是JavaCC解析器生成器。PMD结合运用JavaCC和EBNF(扩展巴科斯-诺尔范式,Extended Backus-Naur Formal)语法,再加上JJTree,把Java源代码解析成抽象语法树(AST,Abstract Syntax Tree)。显然,这句话不那么好懂,且看下文具体说明。
从根本上看,Java源代码只是一些普通的文本。不过,为了让解析器承认这些普通的文本是合法的Java代码,它们必须符合某种特定的结构要求。这种结构可以用一种称为EBNF的句法元语言表示,通常称为“语法”(Grammar)。JavaCC根据语法要求生成解析器,这个解析器就可以用于解析用Java编程语言编写的程序。
不过实际运行中的PMD还要经过JJTree的一次转换。JJTree是一个JavaCC的插件,通过AST扩充JavaCC生成的解析器。AST是一个Java符号流之上的语义层。有了JJTree,语法分析的结果不再是“System, ., out, ., . println”之类的符号序列,而是一个由对象构成的树型层次结构。例如,下面是一段简单的Java代码以及与之对应的AST。
Java源代码: public class Foo { public void bar() { System.out.println("hello world"); } } 对应的抽象语法树 CompilationUnit TypeDeclaration ClassDeclaration UnmodifiedClassDeclaration ClassBody ClassBodyDeclaration MethodDeclaration ResultType MethodDeclarator FormalParameters Block BlockStatement Statement StatementExpression PrimaryExpression PrimaryPrefix Name PrimarySuffix Arguments ArgumentList Expression PrimaryExpression PrimaryPrefix Literal |
四、编写规则
前面我们看到了Java源代码以及与之对应的对象层次结构。下面我们就要利用这些对象编写PMD规则检查代码存在的问题。
一般地,一个PMD规则可以看成一个Visitor,它遍历AST,寻找多个对象之间的一种特定模式,这种模式表示代码存在的问题。问题模式可能简单也可能复杂,简单的如查找代码中是否包含new Thread关键词,复杂的如确定一个类是否正确覆盖了equals和hashcode。
下面是一个寻找空if语句的简单PMD规则。
//扩展AbstractRule,以启用Visitor模式 public class EmptyIfStmtRule extends AbstractRule implements Rule { //当源代码中出现一个Block,下面的方法被调用 public Object visit(ASTBlock node, Object data){ //如果父节点是一个if语句且代码块里面没有任何内容 if ((node.jjtGetParent().jjtGetParent() instanceof ASTIfStatement) && node.jjtGetNumChildren()==0) { //肯定代码存在问题。把一个RuleViolation加入到Report。 RuleContext ctx = (RuleContext)data; ctx.getReport().addRuleViolation(createRuleViolation(ctx, node.getBeginLine())); } //继续检查树的下一个节点 return super.visit(node, data); } } |
也许你不能一下子掌握这段代码,其实它的思路还是比较简单的:
#扩展AbstractRule基类。
#声明一个“钩子”,一旦我们感兴趣的节点出现,它就会被调用(称为“回调”)。在上面的例子中,我们要求在每一个ASTBlock出现时得到通知,所以声明visit(ASTBlock node, Object data)。
#在回调函数中,判断是否出现了我们正在检查的问题。本例我们检查是否存在空的if块,所以先判断当前是否在ASTIfStatement之内,然后判断它是否有子节点。
当然,我们还可以按照另一种方法进行检查:声明一个要求检查ASTIfStatement的回调函数,然后在回调函数中检查是否存在子节点。
五、配置规则
写好自定义规则之后,接下来要把它加入到某个PMD规则集。所谓PMD规则集,就是由一组PMD规则构成的集合。每个PMD规则集由一个XML文件定义,下面是一个PMD规则的配置信息的例子:
<rule name="EmptyIfStmt" message="避免使用空的if语句" class="net.sourceforge.pmd.rules.EmptyIfStmtRule"> <description> 找到空的if语句:if检查了条件,但if块里面没有任何内容。 </description> <priority>3</priority> <example> <![CDATA[ if (absValue < 1) { // not good } </XMLCDATA> </example> </rule> |
可以看出,规则配置文件包含了许多有用的信息。要运行新添加的规则,只需把规则集XML文件和Java源代码文件放入CLASSPATH,然后运行PMD。
结束语:本文介绍了PMD如何在不编译代码的情况下分析和寻找代码存在的问题,通过几个简单的例子了解了EBNF语法、JavaCC和AST,以及如何用PMD检查代码存在的问题、如何编写和运用定制PMD规则等。愿PMD能够助你一臂之力!
参考:
DB2数据库建表及插数据一、建表CREATE TABLE DB2表名(T_ID bigint primary key not null,T_DECIMAL decimal(10,5),T_CHAR char(20),T_VARCHAR varchar(20),T_GRAPHIC graphic(20),T_VARGRAPHIC vargr...
Normal 0 7.8 磅 0 2 false false false MicrosoftInternetExplorer4 <!-- /* Font De
成年人的世界都不容易-看看做到年薪50万的程序员,到底有多累?
試圖匹配一個字符串,該字符串可以包含,但是隻有當字符串包含例子:$gt = 'wt>f';preg_match_all("/([A-Za-z<>]+)/", $gt, $gtmatches);?>返回預期:Array([0] => Array([0] => wt>f)[1] => Array([0] => wt>f))但只需更換該>...
http服务器是如何处理http请求的?如图中文字所描述的,左侧是当有请求的时候,http服务器直接调用具体的业务java代码,就得各种判断请求,然后进行处理.(这种方式毫无疑问是不可取的,是一种强耦合)右侧: http服务器不直接调用业务类,而是把具体的请求(http:www.sdsddd/ff/dd.do)交给servlet的容器来处理.容器通过servlet接口调用业务类.因此servlet容器的出现可以http服务器与java业务类解耦的目的,注意: 业务类必须实现servlet接口s.
微信分享的各种坑!!! WXWebpageObject webpage = new WXWebpageObject(); //设置连接 webpage.webpageUrl = "http://www.baidu.com"; WXMediaMessage msg = new WXMediaMessage(webpage);
昨天手贱把administrator账户禁用了后来重启发现你的账户已被停用。请向系统管理员咨询! 本想着重启按F8进入安全模式用CMD命令解除administrator账户。于是无效,原来win10系统下安全模式模块已经放在更新与恢复下面。解决方法:1.进入PE系统修改sethc.exe进程,找到C:\Windows\system32路径下sethc.exe改为sethc.exe.bf
为了更方便地管理博文中涉及的各种代码与工具资源,现在把这些资源迁移到 Google Code 中,有兴趣者可前往下载。Java1、《高效 Java Web 应用开发框架 JessMA v3.3.1 正式发布》 摘要:JessMA(原名:Portal-Basic)是由 JessMA Open Source 开发的一套高效 Java Full-Stack Web 应用开发框架...
mysql报错Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage在执行create table xx as select xx的时候或者在执行tpcc-mysql的tpcc_load 的时候都会遇到这个错误1534, HY000, Wri...
## 一、POST请求的四种常用方式1、application/x-www-form-urlencoded浏览器原生的表单,值为urlencoded之后的 key1=value1&key2=value2......2、multipart/form-data 浏览器原生的文件表单,用于传输文件3、application/json常用的请求头格式,值为json串 {“key...
将如下内容,复制到文本文件中,改扩展名为:.reg双击执行,导入注册表即可。Windows Registry Editor Version 5.00[HKEY_CLASSES_ROOT\Directory\Background\shell\runas]@="在此处打开命令提示符(管理员)""Icon"="cmd.exe""Extended"=""[HKEY_CLASSES_ROO...