Findbugs、PMD、CheckStyle使用分析报告

一、  Findbugs

1.   安装版本

GUI和作为 Eclipse 插件

2.      安装方法

到官方网站下载最新版本FindBugs http://findbugs.sourceforge.net/downloads.html将 edu.umd.cs.findbugs.plugin.eclipse_1.3.9.20090821.zip下载后解压,然后把解压文件夹复制到 Eclipse安装目录下plugins目录中,重启Eclipse。

3.   特点

检查类获jar文件,它基于bugpatterns,将字节码与缺陷模式进行对比。常使用Visitor模式[1]进行分析。

4.   学习重点

理解Findbugs检测器发现的经典问题及其原理。

5.   缺陷清单

http://findbugs.sourceforge.net/bugDescriptions.html

5.缺陷

Hash  equals 不匹配

实例1:重写equals

public classPerson {

   Stringname;

   int age;

   public Person(String name,int age){

      this.name = name;

      this.age = age;

   }

   public boolean equals(Object person){

      if(person !=null){

         Personp = (Person)person;

      if (p.name.equals(name) && p.age ==age){

         return true;

      }

      }

      return false;

   }  public staticvoidmain(String[] args){

      PersonBob1 = newPerson("Bob",22);

      PersonBob2 = newPerson("Bob",22);

     

      if(Bob1.equals(Bob2)){

         System.out.println("equals Bob1 = Bob2");

      }

      if(Bob1.hashCode() ==Bob2.hashCode()){

         System.out.println("hashCode Bob1 = Bob2");

      }

      HashMap<Person,Integer> map = new HashMap<Person, Integer>();

      map.put(Bob1,123);

      if(map.get(Bob2) !=null){

         System.out.println("Bob’s value = "+ map.get(Bob2));

      }

      else{

         System.out.println("Not exist");

      }

   }

}

输出:     equals Bob1 = Bob2

Not existNot exist

描述:重写对象的equals()方法,但是没有重写它的 hashCode方法,或者相反的情况时。

解析:equals被重写时,通常有必要重写hashcode 方法,以维护hashcode 方法的常规协定,该协定声明相等对象必须具有相等的哈希码。否则,重写equals对象针对内容进行比较,但内容相同的对象hashcode不同,若将一个对象作为hashmap键值,无法查找equals比较结果相等的其他对象。

实例2:重写equals 和 hashCode

   public boolean equals(Person p){

      if(p !=null){

      if (p.name.equals(name) && p.age ==age){

         return true;

      }

      }

      return false;

   }  public inthashCode(){

      return age*name.hashCode();

}

输出:     equals Bob1 = Bob2

hashCode Bob1 = Bob2

Not exist

描述:定义一个co-variant 版本的 equals()或 compareTo()方法。

解析:Bob类定义其 equals()方法为布尔 equals(Bob),它覆盖了对象中定义的 equals()方法。因为 Java 代码在编译时解析重载方法的方式,在运行时使用的几乎总是在对象中定义的这个版本的方法,而不是在 Bob中定义的那一个(除非显式将 equals()方法的参数强制转换为 Bob类型)。因此,当这个类的一个实例放入到类集合中的任何一个中时,使用的是 Object.equals()版本的方法,而不是在 Bob中定义的版本。在这种情况下, Bob类应当定义一个接受类型为 Object的参数的 equals()方法。

实例3:重写equals 和 hashCode(正确)

   public boolean equals(Object person){

      if(person !=null){

         Personp = (Person)person;

      if (p.name.equals(name) && p.age ==age){

         return true;

      }

      }

      return false;

   }

   public int hashCode(){

      return age*name.hashCode();

}

输出:     equals Bob1 = Bob2

hashCode Bob1 = Bob2

Bob's value = 123

忽略方法返回值

实例1:

package com;

public class Person {

   public static void main(String[] args){

      StringaString = "bob";

      aString.replace('b', 'p');

      if(aString.equals("pop")){

         System.out.println("This is pop");

      }

      else{

         System.out.println("This is not pop");

      }

   }

}

输出:     This is not pop

描述:忽略方法中返回语句获未将函数返回值赋给变量。

解析:程序员认为他已经用 p 替换了字符串中的所有 b。但所有这类方法都返回一个新字符串,而从来不会改变消息的接收者。新产生的字符串即b.replace('b', 'p'); 的返回值未被赋给新字符串。

实例2:更改为

         package com;

public class Person {

      public staticvoidmain(String[] args){

         String aString = "bob";

         String b = aString.replace('b','p');

         if(b.equals("pop")){

            System.out.println("This is pop");

         }

         else{

            System.out.println("This is not pop");

         }

      }

}

输出:     This is pop

Null指针对null的解引用(dereference)和冗余比较

实例1:

package com;

import java.util.HashMap;

public class Person {

      void eat(){

         System.out.println("eat ok");

      }

      void drink(){

         System.out.println("drink ok");

      }

      public staticvoidmain(String[] args){

HashMap<Integer,Person>map = new HashMap<Integer,Person> ();

         Person person = map.get(123);

            if (person !=null){

               person.eat();

            } 

            person.drink();

      }

}

输出:Exception in thread "main"java.lang.NullPointerException

at com.Person.main(Person.java:20)

描述:代码路径将会或者可能造成 null 指针异常。null 的冗余比较。

解析:如果两个比较值都为 null,那么它们就是冗余的并可能表明代码错误。若person等于null,则最后一行null 指针异常。

实例2:更改为

         public static void main(String[] args){

      PersonBob = newPerson();

HashMap<Integer,Person>map = newHashMap<Integer,Person>();

      map.put(123,Bob);

      Personperson = map.get(123);

         if (person !=null) {

            person.eat();

         } 

         try{

         person.drink();

         }catch(Exception e){

            e.printStackTrace();

         } 

   }

         输出:

                   eat ok

drink ok

初始化之前读取字段

实例:

package com;

import java.util.List;

import java.util.LinkedList;

import java.util.StringTokenizer;

public classPerson { 

   private List<String>actions;

   public Person(StringstartingActions) { 

      StringTokenizertokenizer = newStringTokenizer(startingActions);

      while(tokenizer.hasMoreTokens()) {

         Strings = tokenizer.nextToken();

         actions.add(s);

         System.out.println(s);

      }

   }

   public static void main(String[] args){

      new Person("This is Bob");

   }

}

解析:将产生一个 null 指针异常,因为变量 actions还没有初始化。

实例2:更改为

private List<String> actions = newLinkedList<String>(); 

二、 PMD

1.   安装版本

Eclipse 插件版本

2. 安装方法

1. 在Eclipse中, 点击Help -> Install New Software...

2.  点击 Add..

3.  输入:

Name: PMD for EclipseUpdate Site

URL: http://sourceforge.net/projects/pmd/files/pmd-eclipse/update-site/

4.  点击OK,Next。重启Eclipse。

3.   特点

可以做到检查Java代码中是否含有未使用的变量、是否含有空的抓取块、是否含有不必要的对象等。该软件功能强大,扫描效率高,是Java程序员debug的好帮手。

4.   实例

package com;

import java.util.HashMap;

public classPerson {

   Stringname;

   int age;


   public Person(String name,int age){

      this.name = name;

      this.age = age;

   }

   public boolean equals(Object person)

   {

      if(person !=null){

         Person p = (Person)person;

      if (p.name.equals(name) && p.age ==age){

         return true;

      }

      }

      return false;

   }

   public int hashCode()

   {

      return age*name.hashCode();

   }

   public static void main(String[] args){

      PersonBob1 = new Person("Bob",22);

      PersonBob2 = new Person("Bob",22);

      if(Bob1.equals(Bob2)){

         System.out.println("equals Bob1 = Bob2");

      }

      if(Bob1.hashCode() ==Bob2.hashCode()){

         System.out.println("hashCode Bob1 = Bob2");

      }

      HashMap<Person,Integer> map = new HashMap<Person, Integer>();

      map.put(Bob1,123);

      if(map.get(Bob2) !=null){

         System.out.println("Bob's value = "+ map.get(Bob2));

      }

      else{

         System.out.println("Not exist");

      }

   }

}

5.   规则

规则:变量命名VariableNamingConventions

描述:

A variable naming conventions rule -customize this to your liking. Currently, it

checks for final variables that should befully capitalized and non-final variables

that should not include underscores.

修正:

Person bob1 = new Person("Bob",22);

      Personbob 2= newPerson("Bob",22);


规则:短变量ShortVariable

描述:

Fields, local variables, or parameter namesthat are very short are not helpful to the reader.

修正:

Person personA = (Person)person;


规则:判断顺序混乱ConfusingTernary

描述:

Avoid negation within an"if" expression with an "else" clause.  For example, rephrase:

  if (x != y) diff(); else same();

as:

  if (x == y) same(); else diff();

修正:

if(map.get(bob2) ==null){

         System.out.println("Not exist");

      }

      else{

         System.out.println("Bob's value = " + map.get(bob2));

      }

 

二、  CheckStyle

1.   安装版本

 Eclipse 插件版

2. 安装方法

1. 在Eclipse中, 点击Help -> Install New Software...

2.  点击 Add..

3.  输入:

Name: CheckStyle

URL: http://eclipse-cs.sourceforge.net/update

4.  点击OK,Next。重启Eclipse。

3.   特点

Checkstyle是一款检查Java程序源代码样式的工具,它可以有效的帮助我们检视代码以便更好的遵循代码编写标准,特别适用于小组开发时彼此间的样式规范和统一。

4.   实例

package com;

 

import java.util.HashMap;

 

public classPerson {

   Stringname;

   int age;

  

   public Person(String name,int age){

      this.name = name;

      this.age = age;

   }

  

   public boolean equals(Object person)

   {

      if(person !=null){

         Person p = (Person)person;

      if (p.name.equals(name) && p.age ==age){

         return true;

      }

      }

      return false;

   }

   public int hashCode()

   {

      return age*name.hashCode();

   }

 

   public static void main(String[] args){

      PersonBob1 = new Person("Bob",22);

      PersonBob2 = new Person("Bob",22);

     

      if(Bob1.equals(Bob2)){

         System.out.println("equals Bob1 = Bob2");

      }

      if(Bob1.hashCode() ==Bob2.hashCode()){

         System.out.println("hashCode Bob1 = Bob2");

      }

     

      HashMap<Person,Integer> map = new HashMap<Person, Integer>();

      map.put(Bob1,123);

     

      if(map.get(Bob2) !=null){

         System.out.println("Bob's value = "+ map.get(Bob2));

      }

      else{

         System.out.println("Not exist");

      }

   }

}

5.   规范

规范:左括号前留有空格

 - '{' is not precededwith  whitespace.

规范:多余空行

 Linehas trailing spaces.

规范:缺少package-info.java文件

Missing package-info.java file.


测试用例参考文章:www.ibm.com/developerworks/cn/java/j-findbug1/index.html

非常感谢


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值