floattwoThirds=2/3; // Noncompliant; int division. Yields 0.0 longmillisInYear=1_000*3_600*24*365; // Noncompliant; int multiplication. Yields 1471228928 longbigNum= Integer.MAX_VALUE + 2; // Noncompliant. Yields -2147483647 longbigNegNum= Integer.MIN_VALUE-1; //Noncompliant, gives a positive result instead of a negative one. DatemyDate=newDate(seconds * 1_000); //Noncompliant, won't produce the expected result if seconds > 2_147_483 ... publiclongcompute(int factor){ return factor * 10_000; //Noncompliant, won't produce the expected result if factor > 214_748 }
publicfloatcompute2(long factor){ return factor / 123; //Noncompliant, will be rounded to closest long integer } `合规代码```java floattwoThirds=2f/3; // 2 promoted to float. Yields 0.6666667 longmillisInYear=1_000L*3_600*24*365; // 1000 promoted to long. Yields 31_536_000_000 longbigNum= Integer.MAX_VALUE + 2L; // 2 promoted to long. Yields 2_147_483_649 longbigNegNum= Integer.MIN_VALUE-1L; // Yields -2_147_483_649 DatemyDate=newDate(seconds * 1_000L); ... return factor * 10_000L; }
``` 分析 在Java 中包装类型与基本数据类型存储位置不同。 Java 基本数据类型存放位置 方法参数、局部变量存放在栈内存中的栈桢中的局部变量表 常量存放在常量池中 包装类型如Integer存放位置 常量池 堆内存 Integer 存储在常量池中时可以使用==对比,但当在堆内存中时,使用==对比,实际对比的是两个内存地址而非值。 根据Integer源码, 可以看出数值在-128-127时,会使用cache中的数据,其实也就是常量池。超过范围后新创建Integer,此时数据就无法使用==。 本项规则,主要就是为了避免对比内存地址而引发的错误判断。 ### 四、Boxing and unboxing should not be immediately reversed 装箱(创建int/Integer类型值的对象)和拆箱(将对象中原始值解出来)不应连续操作。 由于在装箱和拆箱期间原始值保持不变,因此在不需要时进行任何操作都是没有意义的。这也适用于自动装箱和自动拆箱(当Java为您隐式处理原始/对象转换时)。 不合规代码 public void examineInt(int a) { //... }
public void examineInteger(Integer a) { // ... }
public void func() { int i = 0; Integer iger1 = Integer.valueOf(0); double d = 1.0;
int dIntValue = new Double(d).intValue(); // Noncompliant
examineInt(new Integer(i).intValue()); // Noncompliant; explicit box/unbox examineInt(Integer.valueOf(i)); // Noncompliant; boxed int will be auto-unboxed
examineInteger(i); // Compliant; value is boxed but not then unboxed examineInteger(iger1.intValue()); // Noncompliant; unboxed int will be autoboxed
Integer iger2 = new Integer(iger1); // Noncompliant; unnecessary unboxing, value can be reused } //... }
}
int dIntValue = (int) d;
examineInt(i);
examineInteger(i); examineInteger(iger1); } ``` 分析 拆箱,与装箱数值没有发生变化,但在大数据量前提下是极其浪费时间。以下实例中,两者耗时相差10倍。此项目检查主要是提高性能。 ```text ### 五、Intermediate Stream methods should not be left unused 中间流方法不应该闲置,应该提供对应的终端操作(流操作有两种类型:中间操作(返回另一个流)和终端操作(返回比流更多的内容)。中间操作是惰性的,如果中间流操作的结果没有提供给终端操作,那么它就没有任何作用) 不合规 ```javascript
``` 合规 int sum = widgets.stream() .filter(b -> b.getColor() == RED) .mapToInt(b -> b.getWeight()) .sum(); Stream<Widget> pipeline = widgets.stream() .filter(b -> b.getColor() == GREEN) .mapToInt(b -> b.getWeight()); sum = pipeline.sum(); ``` ### 六、Loops with at most one iteration should be refactored 循环执行一次应该重构。 不合规
for (int i = 0; i < 10; i++) { // noncompliant, loop only executes once printf(“i is %d”, i); break;
} ... } ``` ### 七、Non-thread-safe fields should not be static 非线程安全的属性不能设置为静态 不合规 public class MyClass { private static SimpleDateFormat format = new SimpleDateFormat("HH-mm-ss"); // Noncompliant private static Calendar calendar = Calendar.getInstance(); // Noncompliant `合规```java private SimpleDateFormat format = new SimpleDateFormat("HH-mm-ss"); private Calendar calendar = Calendar.getInstance(); ``` 分析 线程不安全的类型设置为静态后,对于静态变量来说,类在加载的时候会占用同一个存储区,而每个线程都是公用这个存储区的,因此存在线程安全的问题。 在多并发的过程中容易产生问题,而且问题原因不易跟踪。 ### 八、"InterruptedException" should not be ignored 绝不应该在代码中忽略InterruptedExceptions,在这种情况下,只需将异常计数记录为“忽略”即可。抛出InterruptedException会清除Thread的中断状态,因此,如果未正确处理该异常,则该线程被中断的事实将丢失。相反,应该立即或在清除方法状态后重新抛出InterruptedExceptions-或应该通过调用Thread.interrupt()重新中断线程,即使这应该是单线程应用程序也是如此。任何其他措施可能会导致线程关闭延迟,并丢失该线程被中断的信息-可能未完成其任务。 不合规代码
InterruptedExceptions should never be ignored in the code, and simply logging the exception counts in this case as "ignoring". The throwing of the InterruptedException clears the interrupted state of the Thread, so if the exception is not handled properly the fact that the thread was interrupted will be lost. Instead, InterruptedExceptions should either be rethrown - immediately or after cleaning up the method's state - or the thread should be re-interrupted by calling Thread.interrupt() even if this is supposed to be a single-threaded application. Any other course of action risks delaying thread shutdown and loses the information that the thread was interrupted - probably without finishing its task.
不合规代码:
```java public void run () { try { while (true) { // do stuff } }catch (InterruptedException e) { // Noncompliant; logging is not enough LOGGER.log(Level.WARN, "Interrupted!", e); } }