1、“PreparedStatement” and “ResultSet” methods should be called with valid indices
PreparedStatement 与 ResultSet 参数设置与获取数据由序号 1 开始而非 0。
PreparedStatement ps = con.prepareStatement("SELECT fname, lname FROM employees where hireDate > ? and salary < ?");
ps.setDate(0, date); // Noncompliant
ps.setDouble(3, salary); // Noncompliant
ResultSet rs = ps.executeQuery();
while (rs.next()) {
String fname = rs.getString(0); // Noncompliant
// ...
}
2、 “wait” should not be called when multiple locks are held
wait() 方法不应该在多重锁内被使用,此时线程只释放了内层锁,而没有释放外层锁,可能导致死锁。
synchronized (this.mon1) { // threadB can't enter this block to request this.mon2 lock & release threadA
synchronized (this.mon2) {
this.mon2.wait(); // Noncompliant; threadA is stuck here holding lock on this.mon1
}
}
3、“wait(…)” should be used instead of “Thread.sleep(…)” when a lock is held
当持有锁的当前线程调用 Thread.sleep (…) 时,可能导致死锁问题。因为被挂起的线程一直持有锁。合适的做法是调用锁对象的 wait () 释放锁让其它等待线程运行。
public void doSomething(){
synchronized(monitor) {
while(notReady()){
Thread.sleep(200);
}
process();
}
...
}
应:
public void doSomething(){
synchronized(monitor) {
while(notReady()){
monitor.wait(200);
}
process();
}
...
}
4、Double-checked locking should not be used
单例懒汉模式:当变量没加 volatile 修饰时,不要使用双重检查
public class DoubleCheckedLocking {
private static Resource resource;
public static Resource getInstance() {
if (resource == null) {
synchronized (DoubleCheckedLocking.class) {
if (resource == null)
resource = new Resource();
}
}
return resource;
}
static class Resource {
}
}
应
public class SafeLazyInitialization {
private static Resource resource;
public synchronized static Resource getInstance() {
if (resource == null)
resource = new Resource();
return resource;
}
static class Resource {
}
}
5、Loops should not be infinit
不应该存在死循环。
int j;
while (true) { // Noncompliant; end condition omitted
j++;
}
6、Methods “wait(…)”, “notify()” and “notifyAll()” should not be called on Thread instances
不应该调用线程实例的 “wait (…)”, “notify ()” and “notifyAll ()”。
Thread myThread = new Thread(new RunnableJob());
...
myThread.wait(2000);
7、Printf-style format strings should not lead to unexpected behavior at runtime
因为 Printf 风格格式化是在运行期解读,而不是在编译期检验,所以会存在风险。
String.format("Not enough arguments %d and %d", 1); //Noncompliant; the second argument is missing
String.format("The value of my integer is %d", "Hello World"); // Noncompliant; an 'int' is expected rather than a String
String.format("Duke's Birthday year is %tX", c); //Noncompliant; X is not a supported time conversion character
String.format("Display %0$d and then %d", 1); //Noncompliant; arguments are numbered starting from 1
String.format("%< is equals to %d", 2); //Noncompliant; the argument index '<' refers to the previous format specifier but there isn't one
8、Resources should be closed
打开的资源应该关闭并且放到 finally 块中进行关闭。可以使用 JDK7 的 try-with-resources 表达式
private void readTheFile() throws IOException {
Path path = Paths.get(this.fileName);
BufferedReader reader = Files.newBufferedReader(path, this.charset);
// ...
reader.close(); // Noncompliant
// ...
Files.lines("input.txt").forEach(System.out::println); // Noncompliant: The stream needs to be closed
}
private void doSomething() {
OutputStream stream = null;
try {
for (String property : propertyList) {
stream = new FileOutputStream("myfile.txt"); // Noncompliant
// ...
}
} catch (Exception e) {
// ...
} finally {
stream.close(); // Multiple streams were opened. Only the last is closed.
}
}
标记1、“runFinalizersOnExit” should not be called
默认情况 JVM 退出时是不运行 finalizers 的,System.runFinalizersOnExit 和 Runtime.runFinalizersOnExit 可以在 jvm 退出时运行,但是因为他们不安全而弃用。
public static void main(String [] args) {
...
System.runFinalizersOnExit(true); // Noncompliant
}
protected void finalize(){
doSomething();
}
应:
Runtime.addShutdownHook(new Runnable() {
public void run(){
doSomething();
}
});
2、“ScheduledThreadPoolExecutor” should not have 0 core threads
java.util.concurrent.ScheduledThreadPoolExecutor 由 corePoolSize 指定核心线程数,如果设置为 0 表示线程池无线程可用且不做任何事。
3、 “super.finalize()” should be called at the end of “Object.finalize()” implementations
protected void finalize() {
releaseSomeResources();
super.finalize (); // 调用,最后调用
}
4、Dependencies should not have “system” scope
maven 依赖不应该有 system 类型的依赖范围,使得系统的可移植性低。
<dependency>
<groupId>javax.sqlgroupId>
<artifactId>jdbc-stdextartifactId>
<version>2.0version>
<scope>systemscope>
<systemPath>/usr/bin/lib/rt.jarsystemPath>
dependency>
5、Locks should be released
保证锁能够被释放
public class MyClass {
private Lock lock = new Lock();
public void doSomething() {
lock.lock(); // Noncompliant
if (isInitialized()) {
// ...
lock.unlock();
}
}
}
应:
public class MyClass {
private Lock lock = new Lock();
public void doSomething() {
if (isInitialized()) {
lock.lock();
// ...
lock.unlock();
}
}
}
标记6、The signature of “finalize()” should match that of "Object.finalize()"
普通方法不应该以 finalize 命名。以免和 Object.finalize() 方法混淆。
public int finalize(int someParameter) { // Noncompliant
/* ... */
}
应:
public int someBetterName(int someParameter) { // Compliant
/* ... */
}
7、Zero should not be a possible denominator
分母不应该为零
void test_divide() {
int z = 0;
if (unknown()) {
// ..
z = 3;
} else {
// ..
}
z = 1 / z; // Noncompliant, possible division by zero
}
标记1、".equals()" should not be used to test the values of “Atomic” classes
不要使用 equals 方法对 AtomicXXX 进行是否相等的判断
Atomic 变量是设计来无锁解决原子性问题的,逻辑上他永远只会和自身相等,Atomic 变量没有重写 equals () 方法。
2、"=+" should not be used instead of "+="
“=+” 与 “+=” 意义不同
a =+ b; 虽然正确但写法不合规,应写成 a = +b。
int target = -5;
int num = 3;
target =- num; // Noncompliant; target = -3. Is that really what's meant?
target =+ num; // Noncompliant; target = 3
应:
int target = -5;
int num = 3;
target = -num; // Compliant; intent to assign inverse value of num is clear
target += num;
标记3、“BigDecimal(double)” should not be used
因为浮点的不精确,使用 BigDecimal (double) 可能得不到期望的值。
推荐:浮点精度运算不精确的原因
double d = 1.1;
BigDecimal bd1 = new BigDecimal(d); // Noncompliant; see comment above
BigDecimal bd2 = new BigDecimal(1.1); // Noncompliant; same result
应:
double d = 1.1;
BigDecimal bd1 = BigDecimal.valueOf(d);
BigDecimal bd2 = new BigDecimal("1.1"); // using String constructor will result in precise value
4、 “Double.longBitsToDouble” should not be used for "int"
Double.longBitsToDouble 返回给定的位所代表的 double 值,需要一个 64 位的 long 类型参数。
int i = 42;
double d = Double.longBitsToDouble(i); // Noncompliant
5、“equals” method overrides should accept “Object” parameters
equals 作为方法名应该仅用于重写 Object.equals (Object) 来避免混淆。
class MyClass {
private int foo = 1;
public boolean equals(MyClass o) { // Noncompliant; does not override Object.equals(Object)
return o != null && o.foo == this.foo;
}
public static void main(String[] args) {
MyClass o1 = new MyClass();
Object o2 = new MyClass();
System.out.println(o1.equals(o2)); // Prints "false" because o2 an Object not a MyClass
}
}
class MyClass2 {
public boolean equals(MyClass2 o) { // Ignored; `boolean equals(Object)` also present
//..
}
public boolean equals(Object o) {
//...
}
}
应:
class MyClass {
private int foo = 1;
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
MyClass other = (MyClass)o;
return this.foo == other.foo;
}
/* ... */
}
class MyClass2 {
public boolean equals(MyClass2 o) {
//..
}
public boolean equals(Object o) {
//...
}
}
6、“Externalizable” classes should have no-arguments constructors
Externalizable (可序列化与反序列化) 类应该有无参构造器。
Externalizable 类是处理其自己的序列化和反序列化的类。在反序列化期间,过程的第一步是使用类的无参数构造函数的默认实例化。因此,没有 no-arg 构造函数的 Externalizable 类不能反序列化
public class Tomato implements Externalizable { // Noncompliant; no no-arg constructor
public Tomato (String color, int weight) { ... }
}
应:
public class Tomato implements Externalizable {
public Tomato() { ... }
public Tomato (String color, int weight) { ... }
}
7、“getClass” should not be used for synchronization
因为 this.getClass() 是以对象作为锁,所以该代码块仍然允许多个线程共同访问。
{
synchronized (this.getClass())
} 错误 子类继承此方法时不能做到同步
{
synchronized (MyClass.class)
} 正确
8、“hashCode” and “toString” should not be called on array instances
String[] args;
args 属于 Object 类型,调用 str.toString() 方法相当于调用 Object.toString() 方法。
使用 Arrays.toString (args) 和 Arrays.hashCode (args) 代替 args.toString() 和 args.hashCode()。
String argStr = args.toString(); // Noncompliant
int argHash = args.hashCode(); // Noncompliant
9、“InterruptedException” should not be ignored
抛出 InterruptedException 后,会取消 Thread 的中断状态,所以在未正确处理该异常的前提下,可以通过调用 Thread.interrupt() 重新中断线程。
public void run () {
try {
while (true) {
// do stuff
}
}catch (InterruptedException e) { // Noncompliant; logging is not enough
LOGGER.log(Level.WARN, "Interrupted!", e);
}
}
应:
try {
while (true) {
// do stuff
}
}catch (InterruptedException e) {
LOGGER.log(Level.WARN, "Interrupted!", e);
// Restore interrupted state...
Thread.currentThread().interrupt();
}
10、“Iterator.hasNext()” should not call "Iterator.next()"
错误用法:
public class FibonacciIterator implements Iterator<Integer>{
...
@Override
public boolean hasNext() {
if(next() != null) {
return true;
}
return false;
}
...
}
标记11、“notifyAll” should be used
notify 可能不能唤醒正确的线程,notifyAll 代之。
12、“null” should not be used with "Optional"
在使用 Optional 封装对象时,永远不会存在从调用返回或接收 null 的问题。
public void doSomething () {
Optional<String> optional = getOptional();
if (optional != null) { // Noncompliant
// do something with optional...
}
}
@Nullable // Noncompliant
public Optional<String> getOptional() {
// ...
return null; // Noncompliant
}
应:
public void doSomething () {
Optional<String> optional = getOptional();
optional.ifPresent(
// do something with optional...
);
}
public Optional<String> getOptional() {
// ...
return Optional.empty();
}
13、“read” and “readLine” return values should be used
从某些数据源读取的数据的方法时,应存储该数据而不是将其丢弃,任何其他措施肯定是一个错误。
public void doSomethingWithFile(String fileName) {
BufferedReader buffReader = null;
try {
buffReader = new BufferedReader(new FileReader(fileName));
while (buffReader.readLine() != null) { // Noncompliant
// ...
}
} catch (IOException e) {
// ...
}
}
应
public void doSomethingWithFile(String fileName) {
BufferedReader buffReader = null;
try {
buffReader = new BufferedReader(new FileReader(fileName));
String line = null;
while ((line = buffReader.readLine()) != null) {
// ...
}
} catch (IOException e) {
// ...
}
}
14、“SingleConnectionFactory” instances should be set to "reconnectOnException"
使用 Spring SingleConnectionFactory 而不启用 reconnectOnException 设置当连接恶化将阻止自动连接恢复。
<bean id="singleCF" class="org.springframework.jms.connection.SingleConnectionFactory">
<constructor-arg ref="dummyConnectionFactory" />
bean>
应
<bean id="singleCF" class="org.springframework.jms.connection.SingleConnectionFactory" p:reconnectOnException="true">
<constructor-arg ref="dummyConnectionFactory" />
bean>
15、“StringBuilder” and “StringBuffer” should not be instantiated with a character
初始化 StringBuilder/StringBuffer 时,如果传入单字符,那么单字符会被识别为其 ASCII 码对应的数字大小。
StringBuffer foo = new StringBuffer ('x'); //错 equivalent to StringBuffer foo = new StringBuffer (120);
StringBuffer foo = new StringBuffer ("x"); //对
16、“toString()” and “clone()” methods should not return null
可返回 “”
在对象上调用 toString() 或 clone() 应该始终返回字符串或对象。相反,返回null会违反该方法的隐式协定。
17、 “wait”, “notify” and “notifyAll” should only be called when a lock is obviously held on an object
先要获得对象锁才能进行上述操作
private void removeElement() {
while (!suitableCondition()){
obj.wait();
}
... // Perform removal
}
or
private void removeElement() {
while (!suitableCondition()){
wait();
}
... // Perform removal
}
应:
private void removeElement() {
synchronized(obj) {
while (!suitableCondition()){
obj.wait();
}
... // Perform removal
}
}
or
private synchronized void removeElement() {
while (!suitableCondition()){
wait();
}
... // Perform removal
}
18、A “for” loop update clause should move the counter in the right direction
检查 for 循环下标递增或递减正确
public void doSomething(String [] strings) {
for (int i = 0; i < strings.length; i--) { // Noncompliant;
String string = strings[i]; // ArrayIndexOutOfBoundsException when i reaches -1
//...
}
19、All branches in a conditional structure should not have exactly the same implementation
程序分支中不应该有相同的实现
switch (i) { // Noncompliant
case 1:
doSomething();
break;
case 2:
doSomething();
break;
case 3:
doSomething();
break;
default:
doSomething();
}
20、Blocks should be synchronized on “private final” fields or parameters
synchronized 同步块应该锁在 private final 属性或参数上,因为同步块内非 final 类型的锁对象可能会出现引用改变。
private String color = "red";
private void doSomething(){
synchronized(color) { // Noncompliant; lock is actually on object instance "red" referred to by the color variable
//...
color = "green"; // other threads now allowed into this block
// ...
}
synchronized(new Object()) { // Noncompliant this is a no-op.
// ...
}
}
应:
private String color = "red";
private final Object lockObj = new Object();
private void doSomething(){
synchronized(lockObj) {
//...
color = "green";
// ...
}
}
21、Child class methods named for parent class methods should be overrides
子类的方法名是父类方法名时,子类方法应该是重写了父类方法。
以下情况不是重写:
a、父类方法是 static 的而子类方法不是 static 的
b、子类方法的参数或返回值与父类方法不是同一个包
c、父类方法是 private
为了不产生混乱,不要与父类方法同名
22、Classes extending java.lang.Thread should override the “run” method
线程类应该重写 run 方法
public class MyRunner extends Thread { // Noncompliant; run method not overridden
public void doSometing() {...}
}
Exceptions:
class MyThread extends Thread { // Compliant - calling super constructor with a Runnable
MyThread(Runnable target) {
super(target); // calling super constructor with a Runnable, which will be used for when Thread.run() is executed
// ...
}
}
23、Classes should not be compared by name
不要用类名称比较类是否相同,而用 instanceof 或者 Class.isAssignableFrom () 进行基础类型比较
if ("Pear".equals(item.getClass().getSimpleName())) { // Noncompliant
return true; // Results in throwing away week-old computers
}
return false;
24、Collection sizes and array length comparisons should make sense
集合大小和数组长度比较应该有意义。
集合的大小和数组的长度始终大于或等于零。因此,测试大小或长度大于或等于零是没有意义的,因为结果始终为真。类似地,测试它小于零将始终返回false。可能的目的是检查集合或数组的非空性。
if (myList.size() >= 0) { ... }
if (myList.size() < 0) { ... }
boolean result = myArray.length >= 0;
if (0 > myArray.length) { ... }
应:
if (!myList.isEmpty()) { ... }
if (myArray.length >= 42) { ... }
25、Collections should not be passed as arguments to their own methods
集合实例不应该作为参数被传给集合自已的方法
1.要么是代码错误
2.要么仅仅是无意义的代码
3.由于某些方法要求参数在执行期间保持不变,因此将集合传递给自身可能导致未知的异常。
List <Object> objs = new ArrayList<Object>();
objs.add("Hello");
objs.add(objs); // Noncompliant; StackOverflowException if objs.hashCode() called
objs.addAll(objs); // Noncompliant; behavior undefined
objs.containsAll(objs); // Noncompliant; always true
objs.removeAll(objs); // Noncompliant; confusing. Use clear() instead
objs.retainAll(objs); // Noncompliant; NOOP
26、Conditionally executed blocks should be reachable
条件执行块应该有可达性
a = false;
if (a) { // Noncompliant
doSomething(); // never executed
}
if (!a || b) { // Noncompliant; "!a" is always "true", "b" is never evaluated
doSomething();
} else {
doSomethingElse(); // never executed
27、Consumed Stream pipelines should not be reused
流不应该重用
流操作分为中间操作和终端操作,并合并以形成流管道。执行终端操作后,流管道被视为已消耗,无法再次使用。这样的重用将产生意想不到的结果。
Stream<Widget> pipeline = widgets.stream().filter(b -> b.getColor() == RED);
int sum1 = pipeline.sum();
int sum2 = pipeline.mapToInt(b -> b.getWeight()).sum(); // Noncompliant
28、Custom serialization method signatures should meet requirements
自定义类序列化方法名称应该符合要求
public class Watermelon implements Serializable {
// ...
void writeObject(java.io.ObjectOutputStream out)// Noncompliant; not private
throws IOException
{...}
public void readObjectNoData() // Noncompliant; not private
{...}
}
29、Dissimilar primitive wrappers should not be used with the ternary operator without explicit casting
不同的原始包装类如果没有明确的类转换不能用于三元操作中
Integer i = 123456789;
Float f = 1.0f;
// 如果 condition 为真,将 i 赋值给 n,会导致类型转换异常。
Number n = condition ? i : f;
30、Exception should not be created without being thrown
不被抛出的异常不要创建
if (x < 0)
new IllegalArgumentException("x must be nonnegative");
应:
if (x < 0)
throw new IllegalArgumentException("x must be nonnegative");
31、Expressions used in “assert” should not produce side effects
assert 表达式不要出现有效的逻辑表达式,即不要改变数据状态
由于assert语句默认情况下不执行(必须使用 JVM 标志启用),因此我们不应依赖其执行。
Idea 开启断言:
assert myList.remove(myList.get(0)); // Noncompliant
应:
boolean removed = myList.remove(myList.get(0));
assert removed;
32、Getters and setters should be synchronized in pairs
get 与 set 应该成对进行同步操作,即在 get 中加锁,那么 set 中也应该加锁。
public class Person {
String name;
public synchronized void setName(String name) {
this.name = name;
}
public String getName() { // Noncompliant
return this.name;
}
}
应:
public class Person {
String name;
public synchronized void setName(String name) {
this.name = name;
}
public synchronized String getName() {
return this.name;
}
}
33、Identical expressions should not be used on both sides of a binary operator
相同的表达式不要作为二元操作的操作数使用,应该简化
if ( a != a ) { // always false
doY();
}
int j = 5 / 5; //always 1
Exceptions:
int i = 1 << 1; // Compliant
34、Inappropriate “Collection” calls should not be made
正确使用集合类型的方法
List<String> list = new ArrayList<String>();
Integer integer = Integer.valueOf(1);
if (list.contains(integer)) { // Noncompliant. Always false.
list.remove(integer); // Noncompliant. list.add(integer) doesn't compile, so this will always return false
}
标记35、Inappropriate regular expressions should not be used
正确使用正则表达式
String str = "/File|Name.txt";
String clean = str.replaceAll(".",""); // Noncompliant; probably meant to remove only dot chars, but returns an empty string
String clean2 = str.replaceAll("|","_"); // Noncompliant; yields _/_F_i_l_e_|_N_a_m_e_._t_x_t_
String clean3 = str.replaceAll(File.separator,""); // Noncompliant; exception on Windows
标记36、Intermediate Stream methods should not be left unused
中间流应该被使用
widgets.stream().filter(b -> b.getColor() == RED); // Noncompliant
应:
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();
37、Invalid “Date” values should not be used
正确使用日期
Date d = new Date();
d.setDate(25);
d.setYear(2014);
d.setMonth(12); // Noncompliant; rolls d into the next year
Calendar c = new GregorianCalendar(2014, 12, 25); // Noncompliant
if (c.get(Calendar.MONTH) == 12) { // Noncompliant; invalid comparison
// ...
}
38、Jump statements should not occur in “finally” blocks
finally 块中使用 return, break, throw 等跳转表达式,会阻止在 try catch 中抛出的未处理异常的传播
public static void main(String[] args) {
try {
doSomethingWhichThrowsException();
System.out.println("OK"); // incorrect "OK" message is printed
} catch (RuntimeException e) {
System.out.println("ERROR"); // this message is not shown
}
}
public static void doSomethingWhichThrowsException() {
try {
throw new RuntimeException();
} finally {
for (int i = 0; i < 10; i ++) {
//...
if (q == i) {
break; // ignored
}
}
/* ... */
return; // Noncompliant - prevents the RuntimeException from being propagated
}
}
39、Loop conditions should be true at least once
循环至少应该走一次
40、Methods should not be named “hashcode” or "equal"
不要使用 hashcode、equal 作为方法名,可能会和 hashCode、equals 出现混淆,导致可读性差。
标记41、Non-public methods should not be "@Transactional"
非 public 方法不要注解 Transactional, 否则可能导致运行时异常
42、Non-serializable classes should not be written
不要忘记实现序列化接口。执行写操作的类要序列化,否则会抛出异常
43、Non-serializable objects should not be stored in “HttpSession” objects
HttpSession 要保存可序列化的对象
public class Address {
//...
}
//...
HttpSession session = request.getSession();
session.setAttribute("address", new Address()); // Noncompliant; Address isn't serializable
44、Non-thread-safe fields should not be static
非线程安全的属性不应该静态化,静态化会导致所有类对象共享该变量,更容易导致线程安全问题。
public class MyClass {
static private SimpleDateFormat format = new SimpleDateFormat("HH-mm-ss"); // Noncompliant
static private Calendar calendar = Calendar.getInstance(); // Noncompliant
}
45、Null pointers should not be dereferenced
空指针引用不应被直接访问,要增加判空检验
@CheckForNull
String getName(){...}
public boolean isNameEmpty() {
return getName().length() == 0; // Noncompliant; the result of getName() could be null, but isn't null-checked
}
46、Optional value should only be accessed after calling isPresent()
Optional 实例值的获取要 isPresent() 之后再做操作:Optional.get() 存在一个值,则返回该值,否则抛出 NoSuchElementException
Optional<String> value = this.getOptionalValue();
// ...
String stringValue = value.get(); // Noncompliant
应:
Optional<String> value = this.getOptionalValue();
// ...
if (value.isPresent()) {
String stringValue = value.get();
}
or
Optional<String> value = this.getOptionalValue();
// ...
String stringValue = value.orElse("default");
标记47、Raw byte values should not be used in bitwise operations in combination with shifts
原始字节值不应参与位运算
result = (result << 8) | readByte(); // Noncompliant
应:
result = (result << 8) | (readByte() & 0xff);
标记48、Reflection should not be used to check non-runtime annotations
反射操作不应该用于检查非运行时注解
Method m = String.class.getMethod("getBytes", new Class[] {int.class,
int.class, byte[].class, int.class});
if (m.isAnnotationPresent(Override.class)) { // Noncompliant; test will always return false, even when @Override is present in the code
即使代码中存在@Override,测试也会始终返回false
49、Related “if/else if” statements should not have the same condition
if/else if 中不应该有相同的条件
if (param == 1)
openWindow();
else if (param == 2)
closeWindow();
else if (param == 1) // Noncompliant
moveWindowToTheBackground();
}
50、Return values from functions without side effects should not be ignored
函数返回值没有起作用的应该被遗弃
public void handle(String command){
command.toLowerCase(); // Noncompliant; result of method thrown away
...
}
51、Silly equality checks should not be made
不好的相等检查不应该做,比如非同类型对象的 equal
Spatula spatula = new Spatula();
if (spatula.equals(tree)) { // Noncompliant; unrelated classes
// ...
}
标记52、Synchronization should not be based on Strings or boxed primitives
字符串和封箱类不应该被用作锁定对象,因为它们可能被池化或重用。
private static final String sLock = "LOCK";
public void doSomething() {
synchronized(sLock) { // Noncompliant
// ...
}
}
应:
private static final Object lock3 = new Object();
public void doSomething() {
synchronized(lock) {
// ...
}
}
标记53、The Object.finalize() method should not be called
Object.finalize() 不要人为去调用
根据官方 javadoc 文档,当垃圾回收确定不再有对该对象的引用时,垃圾回收器将在对象上调用此Object.finaliz() 。显式调用此方法会破坏此协议,从而产生误导。
public void dispose() throws Throwable {
this.finalize(); // Noncompliant
}
54、Thread.run() should not be called directly
run() 不应该直接被调用,调用 start ()。
Thread myThread = new Thread(runnable);
myThread.run(); // Noncompliant
应:
Thread myThread = new Thread(runnable);
myThread.start(); // Compliant
标记55、Value-based classes should not be used for locking
基于值的类不要用于锁对象
Optional<Foo> fOpt = doSomething();
synchronized (fOpt) { // Noncompliant
// ...
}
56、Values should not be uselessly incremented
值增减后不存储是代码浪费甚至是 bug
推荐:局部变量表和操作数栈之间的操作关系
public int pickNumber() {
int i = 0;
int j = 0;
i = i++; // Noncompliant; i is still zero
return j++; // Noncompliant; 0 returned
}
57、Variables should not be self-assigned
变量不应该出现自分配,如下:
public void setName(String name) {
name = name;
}
58、Week Year (“YYYY”) should not be used for date formatting
日期格式化错误
Date date = new SimpleDateFormat("yyyy/MM/dd").parse("2015/12/31");
String result = new SimpleDateFormat("YYYY/MM/dd").format(date); //Noncompliant; yields '2016/12/31'
应:
Date date = new SimpleDateFormat("yyyy/MM/dd").parse("2015/12/31");
String result = new SimpleDateFormat("yyyy/MM/dd").format(date); //Yields '2015/12/31' as expected
1、"@NonNull" values should not be set to null
被标注非空的字段,不应该被设置为空
2、“compareTo” results should not be checked for specific values
被重写后的 compareTo 方法可能返回不是具体的值(除 0 外),建议用 >0、<0、=0
compareTo () 方法:
如果这个字符串是等参数字符串那么返回值 0,如果这个字符串是按字典顺序小于字符串参数那么返回小于 0 的值,如果此字符串是按字典顺序大于字符串参数那么返回一个大于 0 的值
3、“compareTo” should not return "Integer.MIN_VALUE"
compareTo 只代表一个不等标识,不代表不等的程度,应返回 - 1,0,1 标识即可
public int compareTo(MyClass) {
if (condition) {
return Integer.MIN_VALUE; // Noncompliant
}
4、 “equals(Object obj)” should test argument type
要比较 obj 的类型是否一样
public boolean equals(Object obj) {
MyClass mc = (MyClass)obj; // Noncompliant
// ...
}
应:
public boolean equals(Object obj) {
if (obj == null)
return false;
if (this.getClass() != obj.getClass())
return false;
MyClass mc = (MyClass)obj;
// ...
}
5、“Iterator.next()” methods should throw "NoSuchElementException"
public String next(){
if(!hasNext()){
throw new NoSuchElementException();
}
...
}
6、“Serializable” inner classes of non-serializable classes should be "static"
序列化非静态内部类将导致尝试序列化外部类,如果外部类不是序列化类,会产生运行时异常,内部类静态化会避免这种情况
7、“toArray” should be passed an array of the proper type
toArray () 无参且强制类型转换会产生运行时异常,应传入一个合适的类弄作参数
public String [] getStringArray(List<String> strings) {
return (String []) strings.toArray(); // Noncompliant; ClassCastException thrown
}
应:
public String [] getStringArray(List<String> strings) {
return strings.toArray(new String[0]);
}
8、Boxing and unboxing should not be immediately reversed
自动拆箱和装箱不需显示转换,依托于语法糖即可
标记9、Double Brace Initialization should not be used
双括号初始化不要用
Map source = new HashMap(){{ // Noncompliant
put("firstName", "John");
put("lastName", "Smith");
}};
此操作如一个 anonymous inner class,如果 anonymous inner class 返回且被其它对象引用,可能产生 memory leaks,既使不产生 memory leaks 也会让大多维护者感到迷惑
10、Ints and longs should not be shifted by zero or more than their number of bits-1
整型与长整型位移操作数应该价于 1 与类型占位数 - 1
11、Math operands should be cast before assignment
数字操作在操作或赋值前要转化
12、Neither “Math.abs” nor negation should be used on numbers that could be "MIN_VALUE"
如果对数值类型的 MIN_VALUE 值进行 Math.abs 与取反操作,得到的仍然是一个负值,而由于逻辑上我们已经认为获得了一个正数,从而导致出错。
标记13、The non-serializable super class of a “Serializable” class should have a no-argument constructor
序列化的类的非序列化父类应有一个无参构造器
14、The value returned from a stream read should be checked
从流中读取的值应先检查再操作
public void doSomething(String fileName) {
try {
InputStream is = new InputStream(file);
byte [] buffer = new byte[1000];
is.read(buffer); // Noncompliant
// ...
} catch (IOException e) { ... }
}
应:
public void doSomething(String fileName) {
try {
InputStream is = new InputStream(file);
byte [] buffer = new byte[1000];
int count = 0;
while (count = is.read(buffer) > 0) {
// ...
}
} catch (IOException e) { ... }
}
标记15、Value-based objects should not be serialized
基于值的对象不应被用于序列化