FINDBUGS错误分析日志

1.Call to equals() comparing different type
 
    大部分都是类型永远不会有这种情况 比如a为DOUBLE类型所以EQUALS只匹配字符串 if(a.equals())或if(a.quals())这类判断是根本不会有用的的

2.Class doesn't override equals in superclass

    super.equals(obj) 调用父类equals方法 一般都是Object的方法,所以这个super可写可不写,一般都是 为了代码的可读性才加上去的

    一般就是重写equals(obj)即可 即public boolean equals(Object obj){ return super.equals(obj);}
    但是如果覆盖了equals()方法的话,则必须要覆盖hashCode()方法。否则FINDBUGS会出现下面的7号BUG:覆盖了equals()方法的话,则必须要覆盖hashCode()方法
    所以 public boolean equals(Object obj){ return super.equals(obj);}
         public int hashCode(){
         return super.hashCode();
     }

此处,借鉴国外的资料:

findbugs: Class doesn't override equals in superclass
This class extends a class that defines an equals method and adds fields, but doesn't define an equals method itself. Thus, equality on instances of this class will ignore the identity of the subclass and the added fields. Be sure this is what is intended, and that you don't need to override the equals method. Even if you don't need to override the equals method, consider overriding it anyway to document the fact that the equals method for the subclass just return the result of invoking super.equals(o).

大概翻译下:
这个类继承了一个定义了(重写了)equals方法并且又增加了字段,但是自己没有定义(重写 override)一个equals方法。
因此,这个类判断实例相等时会忽视掉子类的相等和字类的成员变量值。
你如果确定这就是你想要的,你可以不必重写这个equals方法。尽管你不需要重写equals方法,也要考虑一下重写equals方法,可以这样:子类的equals方法只return 调用
super.equals(0)的结果就行了。


3.Class is Serializable, but doesn't define serialVersionUID

    serialVersionUID 用来表明类的不同版本间的兼容性

    简单来说,Java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地      相应实体(类)的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常。

    当实现java.io.Serializable接口的实体(类)没有显式地定义一个名为serialVersionUID,类型为long的变量时,Java序列化机制会根据编译的class自动生成一个       serialVersionUID作序列化版本比较用,这种情况下,只有同一次编译生成的class才会生成相同的serialVersionUID 。

    如果我们不希望通过编译来强制划分软件版本,即实现序列化接口的实体能够兼容先前版本,未作更改的类,就需要显式地定义一个名为serialVersionUID,类型为long     的变量,不修改这个变量值的序列化实体都可以相互进行串行化和反串行化。

    也就是这个错误 你要定义一个名为 serialVersionUID,类型为long的变量 按照新版Eclipse自动填写规则 就是:
     private static final long serialVersionUID = 1L;

4.Class names shouldn't shadow simple name of superclass
   基本就是这个类的名字跟超类的名字一样但不在一个包里 所以就改下类名啦

5.Comparison of String parameter using == or !=

   原因:当比较两个字符串内容是否相同时,仅当两个字符串在源文件中都是常量时或者是使用intern()来比较才可以用==来比较,否则最好使用对象比较方法equal。附       string比较:

    String str1 = "java";

    String str2 = "java";

    System.out.print(str1==str2);

    结果:true(二者都为常量)

    String str1 = new String("java");

    String str2 = new String("java");

    System.out.print(str1==str2);

    结果:false(二者为对象)

    String str1 = "java";

    String str2 = "blog";

    String s = str1+str2;

    System.out.print(s=="javablog");

    结果:false(s不为常量,为对象)

    String s1 = "java";

    String s2 = new String("java");

    System.out.print(s1.intern()==s2.intern());

    结果:true(但是intern()方法在效率和实现方式上不统一)

6.Call to equals() comparing different types
    equals比较了不同的对象类型 说的是equals要比较相同的对象类型

7.Equals checks for noncompatible operand
    equals()方法比较的是值是否相同,而不是内存指向地址
   就实际情况来看 是因为
   public boolean equals(Object object) {
   if (!(object instanceof DmZzmm)) {
    return false;
   }
         Dxinfo rhs = (Dxinfo) object;
    return new EqualsBuilder().append(this.dxcount, rhs.dxcount).append(this.lxrsjh, rhs.lxrsjh)
      .append(this.dxnr, rhs.dxnr).append(this.fssj, rhs.fssj).append(this.fssl, rhs.fssl)
      .append(this.id,rhs.id).isEquals();
            。。。。
      }
      问题在那里?很简单 这个白痴是拷贝的代码 既然object 不为DmZzmm就为false 而你要执行的是 Dxinfo rhs = (Dxinfo) object; 所以 如果为DMZzmm进入代码 会因      为不是 Dxinfo 类型而不执行下面的代码 如果为Dxinfo 类型 它就直接执行为FALSE!!所以代码毫无意义 只会执行false!!
      所以只需要把
      public boolean equals(Object object) {
   if (object instanceof Dxinfo) {
    Dxinfo rhs = (Dxinfo) object;
    。。。。。。。
   }else{
    return false;
   }
        就可以了 说穿了 就是你准备用instanceof 匹配的类要跟你下面执行的类要一致。。。。

8.equals method always returns false
   equals始终返回false
      嘛。。。就是没继承超类的话要自己写个EQUALS。。。。别写的没意义只有false就是了。。
      public boolean equals(Object o) {
   return (this==o);
}

9.equals() method does not check for null argument
   equals()方法没检查空参数
      2B错误完全不解释

10.Exception is caught when Exception is not thrown
    异常被捕获但没抛出。。。。

     一般人都会这样写代码:


  try{
    //
  }
  catch(Exception ex){
    //
  }
    这样很省事,但是JAVA规范中并不推荐这样做,这样是属于“过泛地捕获异常”,因为try{}中可能出现的异常种类有很多,上面的做法不利于分别处理各种异常,建议根     据业务需求,分别捕获需要特别处理的异常,例子如下:


  try{
    //
  }
  catch(SQLException ex){
    //
  }
  catch(IOException ex){
    //
  }
  catch(Exception ex){
    //
  }
    另外一个是,捕获到的Exception应尽量记录到LOG文件里。


11.Field names should start with a lower case letter
    字段名应该用小写

12.Can't close pw since it is always null
    无法关闭【PW】因为总是为NULL

13.Non-transient non-serializable instance field in serializable class
     在可序列化的类中存在不能序列化或者不能暂存的数据


百度文库链接地址   http://wenku.baidu.com/view/fd012b6d58fafab069dc0227.html


-----------------------------------------------------------------------------------------------------


1  Comparison of String objects using == or !=
    例,override equals方法时容易犯错
if(this.topic != key.getTopic())
    return false;
2 Dead store to newStatusRecord
    定义局部变量后没有引用

3 Invocation of toString on values
   直接调用数组的toString方法
public  Query createQuery(String hql, Object values[],Session session){
  logger.debug(values);
  logger.debug((new StringBuilder()).append("hql=[").append(hql).append("] ").append(((Object)
}

正确的例子,调用Arrays.toString()和Arrays.deepToString()方法。
import java.util.Arrays;
class A{

}
class B{
@Override
public String toString() {
  return "BBBBB";
}
}
public class Test {
public static void main(String[] args) {
 
  Object [] a = {new Integer(0),new Boolean(true),true,new A(),new B()};
 
  Object[][]b ={{new A(),new B()},{new A(),new B()},{new A(),new B()}};
  System.out.println(Arrays.deepToString(b));
 
}
}

4 ignores exceptional return value of java.io.File.mkdirs()
忽略了返回值,应当含有返回值
  public void initFolder() {
if (!exitDir.isDirectory())  {
   exitDir.mkdirs();
   logger.info("===Finishing create exit trade image folder!====");
  }
}
This method returns a value that is not checked. The return value should be checked since it can indicate an unusual or unexpected function execution. For example, the File.delete() method returns false if the file could not be successfully deleted (rather than throwing an Exception). If you don't check the result, you won't notice if the method invocation signals unexpected behavior by returning an atypical return value.
5 不使用new String()定义空的字符串
String alarmCodeCond = new String();
应当
String alarmCodeCond = "";
6 invokes inefficient new Short(short) constructor; use Short.valueOf(short) instead
    JVM缓存数字常量
Short aShort = new Short(12);
应当
Short aShort = Short.valueOf(12);
7 方法命名习惯,首字母小写
     The method name LaneHandShakeService(Short) doesn't start with a lower case letter
     Methods should be verbs, in mixed case with the first letter lowercase, with the first letter of each internal word capitalized.

8  一个primtive的类型的值经过box后马上unbox
Primitive value is boxed then unboxed to perform primitive coercion

exitRecord.setEnOperatorId(new Long(transactRecord.getEnoperatorID()).intValue());
应当直接强制类型转换
exitRecord.setEnOperatorId((int)transactRecord.getEnoperatorID());
9 Call to equals() comparing different types
使用equals()方法比较不同的类,
反例
  StringBuilder builder = new StringBuilder("nihao");
  String string = "nihao";
  builder.equals(string);
10  Check for oddness that won't work for negative numbers
检查奇数的方法:
反例
   if (i % 2 == 1) {
    //...
   }
The code uses x % 2 == 1 to check to see if a value is odd, but this won't work for negative numbers (e.g., (-5) % 2 == -1). If this code is intending to check for oddness, consider using x & 1 == 1, or x % 2 != 0.

11 Load of known null value,null值的不当使用
反例:
if (devIds == null && devIds.size() == 0) {  //...  }

if (null != tempList || tempList.size() != 0) {
            //...
}
if (batchNo == null) {
   throw new Exception("the No. " + batchNo
     + " is not exists!");
  }
12  Method call passes null for nonnull parameter
    对参数为null的情况没做处理
    例

public void method1() {
   String ip = null;
  try {
   ip = InetAddress.getLocalHost().getHostAddress();
  } catch (UnknownHostException e) {
   e.printStackTrace();
  }
  long ipCount = countIpAddress(ip); // 可能会传入空引用
                               //...
}
long countIpAddress(String ip) {
  long ipNum = 0;
  String[] ipArray = ip.split("\\.");
}

修改后:
public void method1() {
   String ip = null;
  try {
   ip = InetAddress.getLocalHost().getHostAddress();
  } catch (UnknownHostException e) {
   e.printStackTrace();
  }
  long ipCount = countIpAddress(ip); // 可能会传入空引用
                               //...
}
long countIpAddress(String ip) {
  long ipNum = 0;
  if (ip == null) {
   return 0;          //或者抛出异常
  }
  String[] ipArray = ip.split("\\.");
                               //...
}

注意:函数入口需要交验入参的合法性。

13 Method concatenates strings using + in a loop
在循环里使用字符串连接,效率低,应该使用StringBuilder/StringBuffer
例:

    String writeData = "";
    for (int i = 0; i < 10; i++) {
     writeData = writeData + "a";
    }
14 Method may fail to close database resource
   没有释放数据库资源
public ResultSet callProcedure(String procedure) {
  Session ses = getSessionForUpdate();
  ResultSet rs = null;
  try {
   Connection conn = ses.connection();
   conn.setAutoCommit(false);
   CallableStatement statement = conn.prepareCall(procedure); //may fail to close CallableStatement
   rs = statement.executeQuery();
   conn.commit();
  } catch (Exception e) {
   e.printStackTrace();
  } finally {
   try {
    ses.close();
   } catch (SQLException e) {
    throw e;
   }
  }
  return rs;
}
应当修改为:
public ResultSet callProcedure(String procedure) {
  Session ses = getSessionForUpdate();
  ResultSet rs = null;
  CallableStatement statement = null;
  try {
   Connection conn = ses.connection();
   conn.setAutoCommit(false);
   statement = conn.prepareCall(procedure);
   rs = statement.executeQuery();
   conn.commit();
  } catch (Exception e) {
   e.printStackTrace();
  } finally {
   try {
    statement.close();
    ses.close();
   } catch (SQLException e) {
    e.printStackTrace();
   }
  }
  return rs;
}
15 Method may fail to close stream
    没有关闭流,可能会导致文件描述符泄露,应该在finally中关闭
   例:
  try {
   FileInputStream in = new FileInputStream(file);
   InputStreamReader inputStreamReader = new InputStreamReader(in);
   BufferedReader reader = new BufferedReader(inputStreamReader);
   //...
   in.close();
   inputStreamReader.close();
   reader.close();
  } catch (IOException e) {
  }
  修改为:
  FileInputStream in = null;
  InputStreamReader inputStreamReader = null;
  BufferedReader reader = null;
  try {
   in = new FileInputStream(file);
   inputStreamReader = new InputStreamReader(in);
   reader = new BufferedReader(inputStreamReader);
   // ...
  } catch (IOException e) {
  } finally {
   try {
    in.close();
   } catch (IOException e) {
    e.printStackTrace();
   }
   try {
    inputStreamReader.close();
   } catch (IOException e) {
    e.printStackTrace();
   }
   try {
    reader.close();
   } catch (IOException e) {
    e.printStackTrace();
   }
  }
16 Method might ignore exception
  
This method might ignore an exception.  In general, exceptions should be handled or reported in some way, or they should be thrown out of the method.
应该将异常 处理、打印或者抛出
反例:
try {
     //...
     } catch (Exception e) {

     }
17 Class defines non-transient non-serializable instance field readerTypeInfo
一个实现了Serializable接口的类,含有非transient 和非serializable 的实例对象域。

This Serializable class defines a non-primitive instance field which is neither transient, Serializable, or java.lang.Object, and does not appear to implement the Externalizable interface or the readObject() and writeObject() methods.  Objects of this class will not be deserialized correctly if a non-Serializable object is stored in this field.

18 Nullcheck of value previously dereferenced
前面获取的对象,现在引用的时候没有交验是否为null
反例:
  Reader reader = null;
  try {
   reader = this.getReaderByName(readerBasicInfo.getByName());
  }  catch (Exception e1) {
   e1.printStackTrace();
   return ReaderStateConst.FAIL;
  }
  DependenceRelation dependenceRelation = new DependenceRelation();
  dependenceRelation.setDescription(reader.getIpAddress());  // 使用前没有做null校验
19  Possible null pointer dereference
   可能存在的空引用
  capInfo = wrapper.wrapperToClient((ReaderCapabilities) object);
  try {
   if (capInfo != null) {
    transactionDs
      .saveReaderCapabilityCom((ReaderCapabilities) object);
   }
  } catch (RuntimeException e) {
   capInfo.setDetailMsg(ReaderStateConst.DB_OPT_FAIL);
   return capInfo;
  }
  capInfo.setDetailMsg(ReaderStateConst.SUCCESSFUL);   //capInfo可能为null
20 引用前需要做空校验
public synchronized void remove(String batNo, int count) {
  List<Task> taskList = commandMap.get(batNo);
  synchronized (taskList) { //使用前需要作null check
   //...
  }
}

21 Possible null pointer dereference in method on exception path

  List<District> districts = null;
  try {
   districts = this.getDistricts(ReaderConst.DESC);
  } catch (Exception e) {
   e.printStackTrace();
  }
  if (start >= districts.size()) { //districts 可能是null
   tableData.setTotalCount(0);
   return tableData;
  }
22 内部类没有引用外部类的属性/方法的时候,应该作为静态内部类。
This class is an inner class, but does not use its embedded reference to the object which created it.  This reference makes the instances of the class larger, and may keep the reference to the creator object alive longer than necessary.  If possible, the class should be made static.

23 包装类的比较应该使用 eueqls,要比较值类型,需要强制类型转换后再使用。
This method compares two reference values using the == or != operator, where the correct way to compare instances of this type is generally with the equals() method. It is possible to create distinct instances that are equal but do not compare as == since they are different objects. Examples of classes which should generally not be compared by reference are java.lang.Integer, java.lang.Float, etc.
例 getTypeCodeID() 和getSpecCodeID() 方法均返回Integer

  if (configReaderInfo.getTypeCodeID() == realReaderInfo.getTypeCodeID()
    && configReaderInfo.getSpecCodeID() == realReaderInfo
      .getSpecCodeID()) {
   return true;
  }
public class NumberTest {
public static void main(String[] args) {
  Integer a = new Integer(1);
  Integer b = new Integer(1);
  System.out.println(a == b);  //结果是false
}
}

24 Write to static field from instance method
  不要通过实例方法给静态变量赋值。

猜你喜欢

转载自ihyperwin.iteye.com/blog/1618587