findbugs错误总结

 本篇是从别人那找到的,为了让我回头查看findbugs错误怎么解决而保存的微笑

有很多问题其实挺隐晦的,比如第三条。还有人会使用==来判断常量字符串和String类型是否相等,这个就是基础不牢的缘故了。

记得把findbugs尽量清零哦。

1.       NP_NULL_ON_SOME_PATH_EXCEPTION

 

类型

必改项

描述

A  reference value which is null on some  exception control path is dereferenced here.  This may lead to aNullPointerException when the code is executed.  Note that because FindBugs  currently does not prune infeasible exception paths, this may be a false  warning.

 

代码调用时,遇到异常分支,可能造成一个对象没有获得赋值依旧保持NULL空指针。接下来如果对这个对象有引用,可能造成NullPointerException空指针异常。

案例

private voidtest_NP_NULL_ON_SOME_PATH_EXCEPTION(String name, String

pass){

User user = null;

int nport = 10;

try{

user = checkUser(name, pass);

if (user == null){

System.out.println("密码错误");

close();

return ;

}

}

catch (SQLException e){

         e.printStackTrace();

}

user.setPort(nport); //这端代码有NP_NULL_ON_SOME_PATH_EXCEPTION

}

代码分析:这里User对象是在try 块中赋值的, 但是由于checkUser 方法赋值失败造成异常,导致User 对象为空后, 直接转入异常处理模块执行 e.printStackTrace();此时并没有返回,接下来执行user.setPort(nport) 时, 必然造成空指针。

 

案例二:

md = null;  

try {   

    md = MessageDigest.getInstance("SHA-256");  

    md.update(bt);  

   } catch (NoSuchAlgorithmException e) {   

    e.printStackTrace();// script1    

   }  

   byte[] digest = md.digest();// script2  

解决方法

案例一:根据代码逻辑实际情况采取解决方法, 在异常情况下考虑好分支路径

 

案例二:bug出现在script2处,在script1处处理相应的exception即可,如throw return

 

2.       NP_NULL_ON_SOME_PATH

 

类型

必改项

描述

There  is a branch of statement that,if executed, guarantees that a null  value will be dereferenced, which would generate aNullPointerException when the code is executed. Of course, the problem might be that  the branch or statement is infeasible and that the null pointer exception  can't ever be executed; deciding that is beyond the ability of FindBugs.

 

对象可能没有重新赋值

案例

 

如在JDBC编程时候,在关闭ResultSet时候(rs.close()),经常会出现这个bug

 

解决方法

解决办法很容易想到,判断是否为null

使用try...catch...finally

 

 

3.       EC_UNRELATED_CLASS_AND_INTERFACE

 

类型

必改项

描述

This  method calls equals(Object) on two references, one of which is a class and  the other an interface, where neither the class nor any of its non-abstract  subclasses implement the interface. Therefore, the objects being compared are  unlikely to be members of the same class at runtime (unless some application  classes were not analyzed, or dynamic class loading can occur at runtime).  According to the contract of equals(), objects of different classes should  always compare as unequal; therefore, according to the contract defined by  java.lang.Object.equals(Object), the result of this comparison will always be  false at runtime.

 

使用equals方法比较不相关的类和接口

案例

StringBuilder  builder = new StringBuilder"nihao";

String  string = "nihao";

builder.equalsstring;

 

解决方法

调用equals()比较不同的类型。

此方法调用相当于两个不同的类类型的引用,没有共同的子类(对象)。

因此,所比较的对象是不太可能在运行时相同的类成员(除非一些

应用类没有分析或动态类加载可以发生在运行时)。据

equals()的规则,不同类的对象应始终比较不平等,因此,根据

java.lang.Object.equals定义的合同(对象),FALSE将永远是比较的结果

在运行时错误。

 

 

4.       UG_SYNC_SET_UNSYNC_GET

 

类型

必改项

描述

This  class contains similarly-named get and set methods where the set method is  synchronized and the get method is not.  This may result in incorrect  behavior at runtime, as callers of the get method will not necessarily see a  consistent state for the object.  The get method should be made  synchronized.

 

这个类包含类似命名的getset方法。在set方法是同步方法和get方法是非同步方法。这可能会导致在运行时的不正确行为,因为调用的get方法不一定返回对象一致状态。 GET方法应该同步。

案例

 

 

解决方法

 

 

 

5.       DLS_DEAD_LOCAL_STORE

 

类型

必改项

描述

This  instruction assigns a value to a local variable, but the value is not read or  used in any subsequent instruction. Often, this indicates an error, because  the value computed is never used.

Note that Sun's  javac compiler often generates dead stores for final local variables. Because  FindBugs is a bytecode-based tool, there is no easy way to eliminate these  false positives.

该指令为局部变量赋值,但在其后的没有对她做任何使用。通常,这表明一个错误,因为值从未使用过。

案例

 

案例二:

String  abc = "abc"; 

String  xyz = new String(""); 

xyz =  abc; 

System.out.println(xyz);

解决方法

删除未使用的本地变量

案例二:

因为String xyz = new String("");

  这一句执行3个动作:  

  1)创建一个引用xyz  

  2)创建一个String对象  

  3)String的引用赋值给xyz

  其中,后面两个动作是多余的,因为后面的程序中你没有使用这个新建的String对象,而是重新给xyz赋值, 

xyz =  abc;所以,只需要String  xyz = abc;就可以了

 

6.       RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE

 

类型

选改项

描述

A  value is checked here to see whether it is null, but this value can't be null  because it was previously dereferenced and if it were null a null pointer  exception would have occurred at the earlier dereference. Essentially, this  code and the previous dereference disagree as to whether this value is  allowed to be null. Either the check is redundant or the previous dereference  is erroneous.

 

案例

出现该bug有两种情况:多余的null检查;前边没有null值检查的。

比如:我们经常会这个使用ActionForm

String  clazzId = request.getParameter("clazzId");// script1

studentForm.setClazzID(clazzId);//  script2

往往会在script2会出现该错误,因为在script1处未检查clazzId是否为null才导致的。

修改为

if(clazzId  != null) {

studentForm.setClazzID(clazzId);

}

 

解决方法

在设置使用clazzId之前先判断其是否为null

 

 

7.       ES_COMPARING_STRINGS_WITH_EQ

 

类型

必改项

描述

This  code comparesjava.lang.String objects for reference equality using the == or != operators.  Unless both strings are either constants in a source file, or have been  interned using the String.intern() method, the same string value may be represented by two different  String objects. Consider using theequals(Object) method  instead.

 

==或者!=去比较String类型的对象

案例

String  str1 = "java";

String  str2 = "java";

System.out.printstr1==str2;

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

String  str1 = new String"java";

String  str2 = new String"java";

System.out.printstr1==str2;

成果:false(二者为对象)

String  str1 = "java";

String  str2 = "blog";

String  s = str1+str2;

System.out.prints=="javablog";

成果:falses不为常量,为对象)

String  s1 = "java";

String  s2 = new String"java";

System.out.prints1.intern()==s2.intern());

成果:true

 

解决方法

String对象进行比较的时候:只有两种情况可以使用== or !=,这两种情况是;仅当两个字符串在源文件中都是常量或者是调用String.intern()方法,使用String的规范化表示形式来进行比较,如果不是这两中情况的话推荐使用.equals(object)方式

 

 

 

8.       NP_NULL_PARAM_DEREF

 

类型

必改项

描述

This  method call passes a null value for a nonnull method parameter. Either the  parameter is annotated as a parameter that should always be nonnull, or  analysis has shown that it will always be dereferenced.

这种方法调用传递一个空值给非空参数。,要这个参明确注释它是非空参数,要么经过分析得出它总是会被引用不可能为空。

 

案例

int  FunctionOneint xint y=0int z=0int w=0);

我们要给z传递整型值8,作如下调用:

FunctionOne8);

显然,编译器无法确定这个8到底要传递给哪个参数。为了达到我们的目的,必须这样调用:

FunctionOne008);

这是x被传递了0y被传递了 0z被传递了8

 

解决方法

我们可以赋予函数参数默认值。

所谓默认值就是在调用时,可以不写某些参数的值,编译器会自动把默认值传递给调用语句中。默认值一般在函数声明中设置;

 

 

9.       UWF_UNWRITTEN_FIELD

 

类型

必改项

描述

This  field is never written.  All reads of it will return the default value.  Check for errors (should it have been initialized?), or remove it if it is  useless.

 

此字段是永远不会写入值。所有读取将返回默认值。检查错误(如果它被初始化?),如果它确实没有用就删除掉。

案例

 

 

解决方法

 

 

 

10.  NP_TOSTRING_COULD_RETURN_NULL

 

类型

必改项

描述

This toString  method seems to return null in some circumstances. A liberal reading of the  spec could be interpreted as allowing this, but it is probably a bad idea and  could cause other code to break. Return the empty string or some other  appropriate string rather than null.

toString方法可能返回null

案例

 

 

解决方法

 

 

 

11.  MF_CLASS_MASKS_FIELD

 

类型

必改项

描述

This  class defines a field with the same name as a visible instance field in a  superclass. This is confusing, and may indicate an error if methods update or  access one of the fields when they wanted the other.

 

子类中定义了和父类中同名的字段。在调用时会出错

案例

 

 

解决方法

 

 

 

12.  NS_DANGEROUS_NON_SHORT_CIRCUIT

 

类型

必改项

描述

This code  seems to be using non-short-circuit logic (e.g., & or |) rather than  short-circuit logic (&& or ||). In addition, it seem possible that,  depending on the value of the left hand side, you might not want to evaluate  the right hand side (because it would have side effects, could cause an  exception or could be expensive.

Non-short-circuit  logic causes both sides of the expression to be evaluated even when the  result can be inferred from knowing the left-hand side. This can be less  efficient and can result in errors if the left-hand side guards cases when  evaluating the right-hand side can generate an error.

See theJava Language Specification for details

代码中使用(& or |)代替(&& or ||)操作,这会造成潜在的危险

案例

 

缺陷详解:解释一下短路与非短路的区别:

1)短路运算(short-circuit

逻辑与(&&):如果左操作数结果为true,则继续计算右操作数;如果左操作数结果为false

,则对右操作数的运算已经没有必要,直接返回结果false,忽略右操作运算。

逻辑或(||):如果左操作数结果为false,则继续计算右操作数;如果左操作数结果为true

,则对右操作数的运算已经没有必要,直接返回结果true,忽略右操作运算。

正确地使用短路运算符,就可以写出节省时间、提高效率的代码。

2)非短路运算(non-short-circuit

逻辑与(&)、逻辑或(|):不管左操作数的运算结果如何,都一律计算右边的操作数。

我们回放的代码使用的是非短路与(&),也就是不管左边的sr !=null

的结果如何,都一律运算右边的sr.getInt(0) == 0,那如果遇到srnull

值的情况,则一样也会调用到sr.getInt(0)显然就会出现空指针异常。

解决方法

解决这个问题的最好选择是改用短路运算与(&&)。

SysDataSet sds =  con.csCommonSP("P_KMS_GETORIGINALFILETREE");

SysRecord sr = sds  != null ? sds.getParamSet() : null;

rs = (sr != null&& sr.getInt(0) == 0) ?  sds.getResultSet() :null;

 

 

13.  HE_EQUALS_USE_HASHCODE

 

类型

必改项

描述

This class  overrides equals(Object), but does not override hashCode(), and inherits the  implementation of hashCode() from java.lang.Object (which returns the identity  hash code, an arbitrary value assigned to the object by the VM).   Therefore, the class is very likely to violate the invariant that equal  objects must have equal hashcodes.

If you  don't think instances of this class will ever be inserted into a HashMap/HashTable,  the recommended hashCode implementation to use is:

public int hashCode() {

  assert false :  "hashCode not designed";

  return 42; // any  arbitrary constant will do

  }

 

一个类覆写了equals方法,没有覆写hashCode方法,使用了Object对象的hashCode方法

案例

 

 

 

解决方法

 

 

 

14.  NP_EQUALS_SHOULD_HANDLE_NULL_ARGUMENT

 

类型

必改项

描述

This  implementation of equals(Object) violates the contract defined by  java.lang.Object.equals() because it does not check for null being passed as  the argument. All equals() methods should return false if passed a null  value.

 

变量调用equals方法时没有进行是否为null的判断

案例

 

 

解决方法

 

 

 

15.  SE_BAD_FIELD

 

类型

必改项

描述

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

 

序列化的类定义了一个非原生实例对象,这个对象是不可序列化的或非java对象,而且没有添加transient关键字,没有实现Externalizable接口或没有添加readObject()writeObject()方法,那么这个类的对象将不能正确的反序列化。

 

案例

示例代码:

publicclassMytest implements Serializable {

    private ThreadmThread;

    protected FileOutputStreamoutputStream ;

    //这两个变量会提示defines  non-transient non-serializable instance field finoutStream

    private Stringstr;

    private Stringstr1;

    privateinti;

 

}

 

解决方法

解决方法:

1:给对象加上transient关键字,对该象将不会被序列化保存和恢复。

publicclassMytest implements Serializable{

    privatetransient ThreadmThread;

    protectedtransient FileOutputStreamoutputStream;

    private Stringstr;

private Stringstr1;

    privateinti;

}

2:实现Externalizable接口代替Serializable接口,对序列化过程进行完全自主控制。Externalizable没有默认序列化机制,我们需要在writeExternal()方法中将希望被序列化的对象的信息写入,在readExternal()中将其恢复,并且writeObject()方法与readObject()方法中保存和恢复对象的顺序必须相同。

publicclass Mytestimplements Externalizable{

    private ThreadmThread;

    protected FileOutputStreamfoutputStream;

    private Stringstr;

    private Stringstr1;

    privateinti;

    @Override

    publicvoid readExternal(ObjectInput  arg0)throws IOException,

           ClassNotFoundException {

       str=(String) arg0.readObject();

       str1=(String) arg0.readObject();

       i= arg0.readInt();

    }

    @Override

publicvoid  writeExternal(ObjectOutput arg0)throws IOException{

       arg0.writeObject(str);

       arg0.writeObject(str1);

  • 0
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值