续接:FindBugs Report 解读(二)
五:Performance关于代码性能相关方面的
1.Bx: Primitive value is boxed and then immediately unboxed (BX_BOXING_IMMEDIATELY_UNBOXED)
对原始值进行装箱,然后立即取消装箱。这可能是在一个未要求装箱的地方进行了手动装箱,从而迫使编译器进行立即撤消装箱的操作
2.Bx: Primitive value is boxed then unboxed to perform primitive coercion (BX_BOXING_IMMEDIATELY_UNBOXED_TO_PERFORM_COERCION)
对原始值进行装箱然后立即把它强制转换为另外一种原始类型。例如:
new Double(d).intValue()应该直接进行强制转换例如:(int) d
3.Bx: Method allocates a boxed primitive just to call toString (DM_BOXED_PRIMITIVE_TOSTRING)
仅仅为了调用封装类的toString()而对原始类型进行封装操作。比这种方法更有效的是调用封装类的toString(…)方法例如:
new Integer(1).toString() 替换为 Integer.toString(1)
new Long(1).toString() 替换为 Long.toString(1)
new Float(1.0).toString() 替换为 Float.toString(1.0)
new Double(1.0).toString() 替换为 Double.toString(1.0)
new Byte(1).toString() 替换为 Byte.toString(1)
new Short(1).toString() 替换为 Short.toString(1)
new Boolean(true).toString() 替换为 Boolean.toString(true)
4.Bx: Method invokes inefficient floating-point Number constructor; use static valueOf instead (DM_FP_NUMBER_CTOR)
使用new Double(double)方法总是会创建一个新的对象,然而使用Double.valueOf(double)方法可以把值保存在编辑器或者class library、JVM中。使用存储值的方式来避免对象的分配可以或得更好的代码性能
除非类必须符合Java 1.5以前的JVM,否则请使用自动装箱或valueOf()方法创建Double和Float实例。
5.Bx: Method invokes inefficient Number constructor; use static valueOf instead (DM_NUMBER_CTOR)
使用new Integer(int)方法总是会创建一个新的对象,然而使用Integer.valueOf(int)方法可以把值保存在编辑器或者class library、JVM中。使用存储值的方式来避免对象的分配可以或得更好的代码性能
除非类必须符合Java 1.5以前的JVM,否则请使用自动装箱或valueOf()方法创建Long, Integer, Short, Character, Byte实例。
6.Dm: The equals and hashCode methods of URL are blocking (DMI_BLOCKING_METHODS_ON_URL)
使用equals和hashCode方法来对url进行资源标识符解析时会引起堵塞。考虑使用java.net.URI来代替。
7.Dm: Maps and sets of URLs can be performance hogs (DMI_COLLECTION_OF_URLS)
方法或者字段使用url的map/set集合。因为equals方法或者hashCode方法来进行资源标识符解析时都会引起堵塞。考虑使用java.net.URI来代替。
8.Dm: Method invokes inefficient Boolean constructor; use Boolean.valueOf(...) instead (DM_BOOLEAN_CTOR)
使用new方法创建一个java.lang.Boolean类型能够的实例对象是浪费空间的,因为Boolean对象是不可变的而且只有两个有用的值。使用Boolean.valueOf()或者Java1.5中的自动装箱功能来创建一个Boolean实例。
9.Dm: Explicit garbage collection; extremely dubious except in benchmarking code (DM_GC)
在代码中显式的调用垃圾回收命名,这样做并不能起作用。在过去,有人在关闭操作或者finalize方法中调用垃圾回收方法导致了很多的性能浪费。这样大规模回收对象时会造成处理器运行缓慢。
10.Dm: Use the nextInt method of Random rather than nextDouble to generate a random integer (DM_NEXTINT_VIA_NEXTDOUBLE)
如果r是一个java.util.Random对象,你可以使r.nextInt(n)生成一个0到n-1之前的随机数,而不是使用(int)(r.nextDouble() * n)
11.Dm: Method invokes inefficient new String(String) constructor (DM_STRING_CTOR)
使用java.lang.String(String)构造函数会浪费内存因为这种构造方式和String作为参数在功能上容易混乱。只是使用String直接作为参数的形式
12.Dm: Method invokes toString() method on a String (DM_STRING_TOSTRING)
调用String.toString()是多余的操作,只要使用String就可以了。
13.Dm: Method invokes inefficient new String() constructor (DM_STRING_VOID_CTOR)
使用没有参数的构造方法去创建新的String对象是浪费内存空间的,因为这样创建会和空字符串“”混淆。Java中保证完成相同的构造方法会产生描绘相同的String对象。所以你只要使用空字符串来创建就可以了。
14.ITA: Method uses toArray() with zero-length array argument (ITA_INEFFICIENT_TO_ARRAY)
当使用集合的toArray()方法时使用数组长度为0的数组作为参数。比这更有效的一种方法是
myCollection.toArray(new Foo[myCollection.size()]),如果数组的长度足够大就可以直接把集合中的内容包装到数组中直接返回从而避免了第二次创建一个新的数组来存放集合中值。
15.SBSC: Method concatenates strings using + in a loop (SBSC_USE_STRINGBUFFER_CONCATENATION)
在循环中构建一个String对象时从性能上讲使用StringBuffer来代替String对象
例如:
// This is bad
String s = "";
for (int i = 0; i < field.length; ++i) {
s = s + field[i];
}
// This is better
StringBuffer buf = new StringBuffer();
for (int i = 0; i < field.length; ++i) {
buf.append(field[i]);
}
String s = buf.toString();
16.SS: Unread field: should this field be static? (SS_SHOULD_BE_STATIC)
类中所包含的final属性字段在编译器中初始化为静态的值。考虑在定义时就把它定义为static类型的。
17.UM: Method calls static Math class method on a constant value (UM_UNNECESSARY_MATH)
在方法中使用了java.lang.Math的静态方法代替常量来使用,使用常量速度和准确度会更好。 以下为Math中的方法产生的值。
Method Parameter
abs -any-
acos 0.0 or 1.0
asin 0.0 or 1.0
atan 0.0 or 1.0
atan2 0.0 cbrt 0.0 or 1.0
ceil -any-
cos 0.0
cosh 0.0
exp 0.0 or 1.0
expm1 0.0
floor -any-
log 0.0 or 1.0
log10 0.0 or 1.0
rint -any-
round -any-
sin 0.0
sinh 0.0
sqrt 0.0 or 1.0
tan 0.0
tanh 0.0
toDegrees 0.0 or 1.0
toRadians 0.0
18.UPM: Private method is never called (UPM_UNCALLED_PRIVATE_METHOD)
定义为Private类型方法从未被调用,应该被删除。
19.UrF: Unread field (URF_UNREAD_FIELD)
类中定义的属性从未被调用,建议删除。
20.UuF: Unused field (UUF_UNUSED_FIELD)
类中定义的属性从未被使用,建议删除。
21.WMI: Inefficient use of keySet iterator instead of entrySet iterator (WMI_WRONG_MAP_ITERATOR)
当方法中接受一个Map类型的参数时,使用keySet的迭代器比使用entrySet的迭代器效率要高。
六:Internationalization关于代码国际化相关方面的
Dm: Consider using Locale parameterized version of invoked method (DM_CONVERT_CASE)
使用平台默认的编码格式对字符串进行大小写转换,这可能导致国际字符的转换不当。使用以下方式对字符进行转换
String.toUpperCase( Locale l )
String.toLowerCase( Locale l )
七:Multithreaded correctness关于代码多线程正确性相关方面的
1.DL: Synchronization on Boolean could lead to deadlock (DL_SYNCHRONIZATION_ON_BOOLEAN)
该代码同步一个封装的原始常量,例如一个Boolean类型。
private static Boolean inited = Boolean.FALSE;
...
synchronized(inited) {
if (!inited) {
init();
inited = Boolean.TRUE;
}
}
...
由于通常只存在两个布尔对象,此代码可能是同步的其他无关的代码中相同的对象,这时会导致反应迟钝和可能死锁
2.DL: Synchronization on boxed primitive could lead to deadlock (DL_SYNCHRONIZATION_ON_BOXED_PRIMITIVE)
该代码同步一个封装的原始常量,例如一个Integer类型。
private static Integer count = 0;
...
synchronized(count) {
count++;
}
...
由于Integer对象可以共享和保存,此代码可能是同步的其他无关的代码中相同的对象,这时会导致反应迟钝和可能死锁
3.DL: Synchronization on interned String could lead to deadlock (DL_SYNCHRONIZATION_ON_SHARED_CONSTANT)
同步String类型的常量时,由于它被JVM中多个其他的对象所共有,这样在其他代码中会引起死锁。
4.DL: Synchronization on boxed primitive values (DL_SYNCHRONIZATION_ON_UNSHARED_BOXED_PRIMITIVE)
同步一个显然不是共有封装的原始值,例如一个Integer类型的对象。例如:
private static final Integer fileLock = new Integer(1);
...
synchronized(fileLock) {
.. do something ..
}
...
它最后被定义为以下方式来代替:private static final Object fileLock = new Object();
5.Dm: Monitor wait() called on Condition (DM_MONITOR_WAIT_ON_CONDITION)
方法中以java.util.concurrent.locks.Condition对象调用wait()。等待一个条件发生时应该使用在Condition接口中定义的await()方法。
6.Dm: A thread was created using the default empty run method (DM_USELESS_THREAD)
这个方法没有通过run方法或者具体声明Thread类,也没有通过一个Runnable对象去定义一个线程,而这个线程出来浪费资源却什么也没有去做。
7.ESync: Empty synchronized block (ESync_EMPTY_SYNC)
该代码包含一个空的同步块:synchronized() {}
8.IS: Inconsistent synchronization (IS2_INCONSISTENT_SYNC)
不合理的同步
9.IS: Field not guarded against concurrent access (IS_FIELD_NOT_GUARDED)
域不是良好的同步访问---
此字段被标注为net.jcip.annotations.GuardedBy,但可以在某种程度上违反注释而去访问
10.JLM: Synchronization performed on Lock (JLM_JSR166_LOCK_MONITORENTER)
实现java.util.concurrent.locks.Lock的对象调用了同步的方法。应该这样处理,对象被锁定/解锁时使用acquire()/ release()方法而不是使用同步的方法。
11.LI: Incorrect lazy initialization of static field (LI_LAZY_INIT_STATIC)
静态域不正确的延迟初始化--
这种方法包含了一个不同步延迟初始化的非volatile静态字段。因为编译器或处理器可能会重新排列指令,如果该方法可以被多个线程调用,线程不能保证看到一个完全初始化的对象。你可以让字段可变来解决此问题
12.LI: Incorrect lazy initialization and update of static field (LI_LAZY_INIT_UPDATE_STATIC)
这种方法包含一个不同步延迟初始化的静态字段。之后为字段赋值,对象存储到该位置后进一步更新或访问。字段后尽快让其他线程能够访问。如果该方法的进一步访问该字段为初始化对象提供服务,然后你有一个非常严重的多线程bug,除非别的东西阻止任何其他线程访问存储的对象,直到它完全初始化。
即使你有信心,该方法是永远不会被多个线程调用时,在它的值还没有被充分初始化或移动,不把它设定为static字段时它可能会更好。
13.ML: Method synchronizes on an updated field (ML_SYNC_ON_UPDATED_FIELD)
对象获取一个可变字段时进行同步。这是没有意义的,因为不同的线程可以在不同的对象同步。
14.MSF: Mutable servlet field (MSF_MUTABLE_SERVLET_FIELD)
一个web服务一般只能创建一个servlet或者jsp的实例(例如:treates是一个单利类),它会被多个线程调用这个实例的方法服务于多个同时的请求。因此使用易变的字段属性产生竞争的情况。
15.MWN: Mismatched notify() (MWN_MISMATCHED_NOTIFY)
此方法调用Object.notify()或Object.notifyAll()而没有获取到该对象的对象锁。调用notify()或notifyAll()而没有持有该对象的对象锁,将导致IllegalMonitorStateException异常。
16.MWN: Mismatched wait() (MWN_MISMATCHED_WAIT)
此方法调用Object.wait()而没有获取到该对象的对象锁。调用wait()而没有持有该对象的对象锁,将导致IllegalMonitorStateException异常。
17.NP: Synchronize and null check on the same field. (NP_SYNC_AND_NULL_CHECK_FIELD)
如果代码块是同步的,那么久不可能为空。如果是空,同步时就会抛出NullPointerException异常。最好是在另一个代码块中进行同步。
18.No: Using notify() rather than notifyAll() (NO_NOTIFY_NOT_NOTIFYALL)
调用notify()而不是notifyAll()方法。 Java的监控器通常用于多个条件。调用notify()只唤醒一个线程,这意味着该线程被唤醒只是满足的当前的唯一条件。
19.RS: Class's readObject() method is synchronized (RS_READOBJECT_SYNC)
序列化类中定义了同步的readObject()。通过定义,反序列化创建的对象只有一个线程可以访问,因此没有必要的readObject()进行同步。如果的readObject()方法本身造成对象对另一个线程可见,那么这本身就是不好的编码方式。
20.Ru: Invokes run on a thread (did you mean to start it instead?) (RU_INVOKE_RUN)
这种方法显式调用一个对象的run()。一般来说,类是实现Runnable接口的,因为在一个新的线程他们将有自己的run()方法,在这种情况下Thread.start()方法调用是正确的。
21.SC: Constructor invokes Thread.start() (SC_START_IN_CTOR)
在构造函数中启动一个线程。如果类曾经被子类扩展过,那么这很可能是错的,因为线程将在子类构造之前开始启动。
22.SP: Method spins on field (SP_SPIN_ON_FIELD)
方法无限循环读取一个字段。编译器可合法悬挂宣读循环,变成一个无限循环的代码。这个类应该改变,所以使用适当的同步(包括等待和通知要求)
23.STCAL: Call to static Calendar (STCAL_INVOKE_ON_STATIC_CALENDAR_INSTANCE)
即使JavaDoc对此不包含暗示,而Calendars本身在多线程中使用就是不安全的。探测器发现当调用Calendars的实例时将会获得一个静态对象。
Calendar rightNow = Calendar.getInstance();
24.STCAL: Call to static DateFormat (STCAL_INVOKE_ON_STATIC_DATE_FORMAT_INSTANCE)
在官方的JavaDoc,DateFormats多线程使用本事就是不安全的。探测器发现调用一个DateFormat的实例将会获得一个静态对象。
myString = DateFormat.getDateInstance().format(myDate);
25.STCAL: Static Calendar (STCAL_STATIC_CALENDAR_INSTANCE)
Calendar在多线程中本身就是不安全的,如果在线程范围中共享一个Calendarde
实例而不使用一个同步的方法在应用中就会出现一些奇怪的行为。在sun.util.calendar.BaseCalendar.getCalendarDateFromFixedDate()中会抛出ArrayIndexOutOfBoundsExceptions
or IndexOutOfBoundsExceptions异常。
26.STCAL: Static DateFormat (STCAL_STATIC_SIMPLE_DATE_FORMAT_INSTANCE)
DateFormat 在多线程中本身就是不安全的,如果在线程范围中共享一个DateFormat的实例而不使用一个同步的方法在应用中就会出现一些奇怪的行为。
27.SWL: Method calls Thread.sleep() with a lock held (SWL_SLEEP_WITH_LOCK_HELD)
当持有对象时调用Thread.sleep()。这可能会导致很差的性能和可扩展性,或陷入死锁,因为其他线程可能正在等待获得锁。调用wait()是一个更好的主意,释放对象的持有以允许其他线程运行。
28.UG: Unsynchronized get method, synchronized set method (UG_SYNC_SET_UNSYNC_GET)
这个类包含类似命名的get和set方法。在set方法是同步方法和get方法是非同步方法。这可能会导致在运行时的不正确行为,因为调用的get方法不一定返回对象一致状态。 GET方法应该同步。
29.UL: Method does not release lock on all paths (UL_UNRELEASED_LOCK)
方法获得了当前的对象所,但是在方法中始终没有释放它。一个正确的示例如下:
Lock l = ...;
l.lock();
try {
// do something
} finally {
l.unlock();
}
30.UL: Method does not release lock on all exception paths (UL_UNRELEASED_LOCK_EXCEPTION_PATH)
方法获得了当前的对象所,但是在所有的异常处理中始终没有释放它。一个正确的示例如下:
Lock l = ...;
l.lock();
try {
// do something
} finally {
l.unlock();
}
31.UW: Unconditional wait (UW_UNCOND_WAIT)
方法中包含调用java.lang.Object.wait(),而却没有放到条件流程控制中。该代码应确认条件尚未满足之前等待;先前任何通知将被忽略。
32.VO: A volatile reference to an array doesn't treat the array elements as volatile (VO_VOLATILE_REFERENCE_TO_ARRAY)
声明一个变量引用数组,这可能不是你想要的。如果一个变量引用数组,那么对引用数组的读和写都是不安全的,但是数组元素不是变量。取得数组的变量值你可以使用java.util.concurrent包中的数组的原子性特性
33.WL: Sychronization on getClass rather than class literal (WL_USING_GETCLASS_RATHER_THAN_CLASS_LITERAL)
实例的方法中同步this.getClass(),如果这个类有子类集合,那么子类集合中的对象将会在这个类的各个子类上进行同步,这不是我们想要的效果,我们只要同步当前的类对象而不包含它的所有子类,可以同步类名.getClass()。例如,java.awt.Label的代码:
private static final String base = "label";
private static int nameCounter = 0;
String constructComponentName() {
synchronized (getClass()) {
return base + nameCounter++;
}
}
Label中的子类集合不可能在同一个子对象上进行同步,替换上面的方法为:
private static final String base = "label";
private static int nameCounter = 0;
String constructComponentName() {
synchronized (Label.class) {
return base + nameCounter++;
}
}
34.WS: Class's writeObject() method is synchronized but nothing else is (WS_WRITEOBJECT_SYNC)
这个类有一个writeObject()方法是同步的,但是这个类中没有其他的同步方法。
35.Wa: Condition.await() not in loop (WA_AWAIT_NOT_IN_LOOP)
方法没有在循环中调用java.util.concurrent.await()。如果对象是用于多种条件,打算调用wait()方法的条件可能不是实际发生的。
36.Wa: Wait not in loop (WA_NOT_IN_LOOP)
这种方法包含调用java.lang.Object.wait(),而这并不是一个循环。如果监视器用于多个条件,打算调用wait()方法的条件可能不是实际发生的。
八:Malicious codevulnerability关于恶意破坏代码相关方面的
1.EI: May expose internal representation by returning reference to mutable object (EI_EXPOSE_REP)
返回一个易变对象引用并把它保存在对象字段中时会暴露对象内部的字段描述,如果接受不守信任的代码访问或者没有检查就去改变易变对象的会涉及对象的安全和其他重要属性的安全。返回一个对象的新副本,在很多情况下更好的办法。
2.EI2: May expose internal representation by incorporating reference to mutable object (EI_EXPOSE_REP2)
此代码把外部可变对象引用存储到对象的内部表示。如果实例受到不信任的代码的访问和没有检查的变化危及对象和重要属性的安全。存储一个对象的副本,在很多情况下是更好的办法。
3.FI: Finalizer should be protected, not public (FI_PUBLIC_SHOULD_BE_PROTECTED)
一个类中的finalize()方法必须声明为protected,而不能为public类型
4.MS: Public static method may expose internal representation by returning array (MS_EXPOSE_REP)
一个public类型的静态方法返回一个数组,可能引用内部属性的暴露。任何代码调用此方法都可以自由修改底层数组。一个解决办法是返回一个数组的副本。
5.MS: Field should be both final and package protected (MS_FINAL_PKGPROTECT)
一个静态字段可能被恶意代码或另外一个包所改变的。字段可以放到protected包中也可以定义为final类型的以避免此问题。
6.MS: Field is a mutable array (MS_MUTABLE_ARRAY)
一个定义为final类型的静态字段引用一个数组时它可以被恶意代码或在另其他包中所使用。这些代码可以自由修改数组的内容。
7.MS: Field is a mutable Hashtable (MS_MUTABLE_HASHTABLE)
一个定义为final类型的静态字段引用一个Hashtable时可以被恶意代码或者在其他包中被调用,这些方法可以修改Hashtable的值。
8.MS: Field should be moved out of an interface and made package protected (MS_OOI_PKGPROTECT)
将域尽量不要定义在接口中,并声明为包保护
在接口中定义了一个final类型的静态字段,如数组或哈希表等易变对象。这些对象可以被恶意代码或者在其他包中被调用,为了解决这个问题,需要把它定义到一个具体的实体类中并且声明为保护类型以避免这种错误。
9.MS: Field should be package protected (MS_PKGPROTECT)
一个静态字段是可以改变的恶意代码或其他的包访问修改。可以把这种类型的字段声明为final类型的以防止这种错误。
十:Dodgy关于代码运行期安全方面的
1.XSS: Servlet reflected cross site scripting vulnerability (XSS_REQUEST_PARAMETER_TO_SEND_ERROR)
在代码中在Servlet输出中直接写入一个HTTP参数,这会造成一个跨站点的脚本漏洞。
2.XSS: Servlet reflected cross site scripting vulnerability (XSS_REQUEST_PARAMETER_TO_SERVLET_WRITER)
代码直接写入参数的HTTP服务器错误页(使用HttpServletResponse.sendError)。表达了类似的不受信任的输入会引起跨站点脚本漏洞。
3.BC: Questionable cast to abstract collection (BC_BAD_CAST_TO_ABSTRACT_COLLECTION)
在代码投把一个集合强制类型转换为一个抽象的集合(如list,set或map)。保证该对象类型和将要转换的类型是一致的。如果你只是想要便利一个集合,那么你就不必将它转换为Set或List。
4.BC: Questionable cast to concrete collection (BC_BAD_CAST_TO_CONCRETE_COLLECTION)
代码把抽象的集合(如List,Set,或Collection)强制转换为具体落实类型(如一个ArrayList或HashSet)。这可能不正确,也可能使您的代码很脆弱,因为它使得难以在今后的切换指向其他具体实现。除非你有特别理由这样做,否则只需要使用抽象的集合类。
5.BC: Unchecked/unconfirmed cast (BC_UNCONFIRMED_CAST)
强制类型转换操作没有经过验证,而且不是所有的此种类型装换过的类都可以再强制类型转换为原类型。在代码中需要进行逻辑判断以保证可以进行这样的操作。
6.BC: instanceof will always return true (BC_VACUOUS_INSTANCEOF)
instanceof测试将始终返回真(除非被测试的值为空)。虽然这是安全,确保它是不是说明一些误解或其他一些逻辑错误。如果你真的想测试是空的价值,也许会更清楚这样做的更好空试验,而不是一个instanceof测试。
7.BSHIFT: Unsigned right shift cast to short/byte (ICAST_QUESTIONABLE_UNSIGNED_RIGHT_SHIFT)
无符号数右移后进行转换为short或者byte类型时可能会丢弃掉高位的值,这样的结果就是有符合数和无符号数无法区分(这取决于移位大小)
8.CI: Class is final but declares protected field (CI_CONFUSED_INHERITANCE)
这个类被声明为final的,而是字段属性却声明为保护类型的。由于是final类,它不能再被继承,而再声明为保护类型的很容易造成混淆。为了从外部能正确的使用它应该把它们声明为private或者public类型。
9.DB: Method uses the same code for two branches (DB_DUPLICATE_BRANCHES)
此方法使用相同的代码,以实现两个有条件的分支。检查以确保这是不是一个编码错误。
10.DB: Method uses the same code for two switch clauses (DB_DUPLICATE_SWITCH_CLAUSES)
他的方法使用相同的代码来实现两个switch的声明条款。这可能是重复代码的情况,但可能也显示出编码的错误。
11.DLS: Dead store to local variable (DLS_DEAD_LOCAL_STORE)
该指令为局部变量赋值,但在其后的没有对她做任何使用。通常,这表明一个错误,因为值从未使用过。
12.DLS: Useless assignment in return statement (DLS_DEAD_LOCAL_STORE_IN_RETURN)
本声明把一个局部变量放到方法的返回语句中。这对于方法中局部变量来说是没有意思的。
13.DLS: Dead store of null to local variable (DLS_DEAD_LOCAL_STORE_OF_NULL)
把一个本地变量赋值为null值,并且再也没有对这个变量做任何的操作。这样可能是为了垃圾回收,而是Java SE 6.0,这已不再需要。
14.DMI: Code contains a hard coded reference to an absolute pathname (DMI_HARDCODED_ABSOLUTE_FILENAME)
此代码包含文件对象为一个绝对路径名(例如,新的文件(“/ home/dannyc/workspace/j2ee/src/share/com/sun/enterprise/deployment”);
15.DMI: Non serializable object written to ObjectOutput (DMI_NONSERIALIZABLE_OBJECT_WRITTEN)
代码中让一个非序列化的对象出现在ObjectOutput.writeObject()方法中,这样会引起一个错误。
16.DMI: Invocation of substring(0), which returns the original value (DMI_USELESS_SUBSTRING)
此代码调用了subString(0)方法,它将返回原来的值。
17.Eq: Class doesn't override equals in superclass (EQ_DOESNT_OVERRIDE_EQUALS)
子类定义了一个新的equals方法但是却不是覆写了父类本省的equals()方法。
18.FE: Test for floating point equality (FE_FLOATING_POINT_EQUALITY)
此操作比较两个浮点值是否相等。由于浮点运算可能会涉及到舍入,计算float和double值可能不准确。如果要求值必须准确,如货币值,可以考虑使用固定精度类型,如BigDecimal类型的值来比较
19.FS: Non-Boolean argument formatted using %b format specifier (VA_FORMAT_STRING_BAD_CONVERSION_TO_BOOLEAN)
使用%b去格式化Boolean类型的值不正确的但是它不会抛出异常,任何非空的值都会输出true,任何为空的值都会输出false
20.IC: Initialization circularity (IC_INIT_CIRCULARITY)
在引用两个相互调用为环状static方法去初始化一个实例时是错误的。
21.ICAST: integral division result cast to double or float (ICAST_IDIV_CAST_TO_DOUBLE)
整形数除法强制转换为double或者float类型。
int x = 2;
int y = 5;
// Wrong: yields result 0.0
double value1 = x / y;
// Right: yields result 0.4
double value2 = x / (double) y;
22.ICAST: Result of integer multiplication cast to long (ICAST_INTEGER_MULTIPLY_CAST_TO_LONG)
整形数做乘法运算结果转换为long值时如果采用
long convertDaysToMilliseconds(int days) { return 1000*3600*24*days; } 结果会因为超出整形的范围而出错。
如果使用:
long convertDaysToMilliseconds(int days) { return 1000L*3600*24*days; }
或者:
static final long MILLISECONDS_PER_DAY = 24L*3600*1000;
long convertDaysToMilliseconds(int days) { return days * MILLISECONDS_PER_DAY; }
都可以避免此问题。
23.IM: Computation of average could overflow (IM_AVERAGE_COMPUTATION_COULD_OVERFLOW)
代码中使用x % 2 == 1的方法去验证运算是否存在余数的情况,但是如果出现负数的情况就不起作用了。使用x & 1 == 1, or x % 2 != 0来代替
24.INT: Vacuous comparison of integer value (INT_VACUOUS_COMPARISON)
整形数进行比较结果总是不变。例如:x <= Integer.MAX_VALUE
25.MTIA: Class extends Servlet class and uses instance variables (MTIA_SUSPECT_SERVLET_INSTANCE_FIELD)
这个类扩展从Servlet类,并使用实例的成员变量。由于只有一个Servlet类的实例,并在多线程方式使用,这种模式有可能存在问题。考虑只使用方法的局部变量。
26.MTIA: Class extends Struts Action class and uses instance variables (MTIA_SUSPECT_STRUTS_INSTANCE_FIELD)
类扩展自Struts的Action类并使用这个实例的成员变量,因为在Struts框架中只存在一个Action实例对象并且使用在多线程的情况下很可能会出现问题。
27.NP: Dereference of the result of readLine() without nullcheck (NP_DEREFERENCE_OF_READLINE_VALUE)
对readLine()的结果值没有进行判空操作就去重新赋值,这样的操作可以会抛出空指针异常。
28.NP: Immediate dereference of the result of readLine() (NP_IMMEDIATE_DEREFERENCE_OF_READLINE)
对readLine()的结果立即赋值,这样的操作可以会抛出空指针异常。
29.NP: Possible null pointer dereference due to return value of called method (NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE)
方法的返回值没有进行是否为空的检查就重新赋值,这样可能会出现空指针异常。
30.NP: Parameter must be nonnull but is marked as nullable (NP_PARAMETER_MUST_BE_NONNULL_BUT_MARKED_AS_NULLABLE)
参数值在任何情况下都不能为空,但是有明确的注释它可以为空。
31.NS: Potentially dangerous use of non-short-circuit logic (NS_DANGEROUS_NON_SHORT_CIRCUIT)
代码中使用(& or |)代替(&& or ||)操作,这会造成潜在的危险。
32.NS: Questionable use of non-short-circuit logic (NS_NON_SHORT_CIRCUIT)
代码中使用(& or |)代替(&& or ||)操作,会引起不安全的操作
33.PZLA: Consider returning a zero length array rather than null (PZLA_PREFER_ZERO_LENGTH_ARRAYS)
考虑返回一个零长度的数组,而不是null值
34.QF: Complicated, subtle or wrong increment in for-loop (QF_QUESTIONABLE_FOR_LOOP)
确定这个循环是正确的变量递增,看起来,另一个变量被初始化,检查的循环。这是由于for循环中太复杂的定义造成的。
35.RCN: Redundant comparison of non-null value to null (RCN_REDUNDANT_COMPARISON_OF_NULL_AND_NONNULL_VALUE)
方法中包含一个不能为空的赋值还包含一个可以为空的赋值。冗余比较非空值为空。
36.RCN: Redundant comparison of two null values (RCN_REDUNDANT_COMPARISON_TWO_NULL_VALUES)
方法中对两个null值进行比较
37.RCN: Redundant nullcheck of value known to be non-null (RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE)
方法中对不为空的值进行为空的判断。
38.REC: Exception is caught when Exception is not thrown (REC_CATCH_EXCEPTION)
在try/catch块中捕获异常,但是异常没有在try语句中抛出而RuntimeException又没有明确的被捕获
39.RI: Class implements same interface as superclass (RI_REDUNDANT_INTERFACES)
子类和父类都实现了同一个接口,这种定义是多余的。
40.RV: Method discards result of readLine after checking if it is nonnull (RV_DONT_JUST_NULL_CHECK_READLINE)
readLine方法的结果不为空时被抛弃
41.RV: Remainder of 32-bit signed random integer (RV_REM_OF_RANDOM_INT)
此代码生成一个随机的符号整数,然后计算另一个值的。由于随机数可以是负数,所以其余操作的结果也可以是负面的。考虑使用Random.nextInt(int)方法代替。
42.SA: Double assignment of local variable (SA_LOCAL_DOUBLE_ASSIGNMENT)
为一个局部变量两次赋值,这样是没有意义的。例如:
public void foo() {
int x,y;
x = x = 17;
}
43.SA: Self assignment of local variable (SA_LOCAL_SELF_ASSIGNMENT)
局部变量使用自身给自己赋值
public void foo() {
int x = 3;
x = x;
}
44.SF: Switch statement found where one case falls through to the next case (SF_SWITCH_FALLTHROUGH)
Switch语句中一个分支执行后又执行了下一个分支。通常case后面要跟break 或者return语句来跳出。
45.SF: Switch statement found where default case is missing (SF_SWITCH_NO_DEFAULT)
Switch没有默认情况下执行的case语句。
46.Se: private readResolve method not inherited by subclasses (SE_PRIVATE_READ_RESOLVE_NOT_INHERITED)
声明为private的序列化方法被子类继承
47.UCF: Useless control flow (UCF_USELESS_CONTROL_FLOW)
没有任何作用的条件语句。
if (argv.length == 0) {
// TODO: handle this case
}
48.UCF: Useless control flow to next line (UCF_USELESS_CONTROL_FLOW_NEXT_LINE)
无效的条件控制语句,注意if (argv.length == 1);以“;”结尾,下面的语句无论是否满足都会运行。
if (argv.length == 1);
System.out.println("Hello, " + argv[0]);
49.UwF: Field not initialized in constructor (UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR)
字段从来没有在任何构造函数初始化,对象被创建后值为空。如果该字段未被定义就重新赋值会产生一个空指针异常。
50.XFB: Method directly allocates a specific implementation of xml interfaces (XFB_XML_FACTORY_BYPASS)
方法自定义了一种XML接口的实现类。最好是使用官方提供的工厂类来创建这些对象,以便可以在运行期中改变。例如:
javax.xml.parsers.DocumentBuilderFactory
javax.xml.parsers.SAXParserFactory
javax.xml.transform.TransformerFactory