本篇是从别人那找到的,为了让我回头查看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 a
代码调用时,遇到异常分支,可能造成一个对象没有获得赋值依旧保持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 a
对象可能没有重新赋值 |
案例 |
如在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.equals(string);
|
解决方法 |
调用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.
这个类包含类似命名的get和set方法。在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 compares
用==或者!=去比较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
|
解决方法 |
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 FunctionOne(int x,int y=0,int z=0,int w=0); 我们要给z传递整型值8,作如下调用: FunctionOne(8); 显然,编译器无法确定这个8到底要传递给哪个参数。为了达到我们的目的,必须这样调用: FunctionOne(0,0,8); 这是x被传递了0,y被传递了 0,z被传递了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,那如果遇到sr为null 值的情况,则一样也会调用到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, or
序列化的类定义了一个非原生实例对象,这个对象是不可序列化的或非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); |