通過Sonar的代碼質量報告學習【如何寫安全高質量的代碼】

1.不要用.size(),改用isEmpty()

Using Collection.size() to test for emptiness works, but using Collection.isEmpty() makes the code more readable and can be more performant. The time complexity of any isEmpty() method implementation should be O(1) whereas some implementations of size() can be O(n).

Noncompliant Code Example

if (myCollection.size() == 0) {  // Noncompliant
  /* ... */
}

Compliant Solution

if (myCollection.isEmpty()) {
  /* ... */
}

2.當catch異常的時候,要麼打Log,要麼Throw出去,不要什麼都不做

When handling a caught exception, the original exception's message and stack trace should be logged or passed forward.

Noncompliant Code Example

 // Noncompliant - exception is lost
try { /* ... */ } catch (Exception e) { LOGGER.info("context"); }

// Noncompliant - exception is lost (only message is preserved)
try { /* ... */ } catch (Exception e) { LOGGER.info(e.getMessage()); }

// Noncompliant - exception is lost
try { /* ... */ } catch (Exception e) { throw new RuntimeException("context"); }

Compliant Solution

try { /* ... */ } catch (Exception e) { LOGGER.info(e); }

try { /* ... */ } catch (Exception e) { throw new RuntimeException(e); }

try {
  /* ... */
} catch (RuntimeException e) {
  doSomething();
  throw e;
} catch (Exception e) {
  // Conversion into unchecked exception is also allowed
  throw new RuntimeException(e);
}

Exceptions

InterruptedExceptionNumberFormatExceptionParseException and MalformedURLException exceptions are arguably used to indicate nonexceptional outcomes. Similarly, dealing with NoSuchMethodExceptionis often required when dealing with the Java reflection API.

Because they are part of Java, developers have no choice but to deal with them. This rule does not verify that those particular exceptions are correctly handled.

int myInteger;
try {
  myInteger = Integer.parseInt(myString);
} catch (NumberFormatException e) {
  // It is perfectly acceptable to not handle "e" here
  myInteger = 0;
}

See

3.已經定義的字符串,不要再使用toString()方法

Invoking a method designed to return a string representation of an object which is already a string is a waste of keystrokes. This redundant construction may be optimized by the compiler, but will be confusing in the meantime.

Noncompliant Code Example

String message = "hello world";
System.out.println(message.toString()); // Noncompliant;

Compliant Solution

String message = "hello world";
System.out.println(message);
4.變量不要初始化爲null,不初始化就可以。

A dead store happens when a local variable is assigned a value, including null, that is not read by any subsequent instruction. Calculating or retrieving a value only to then overwrite it or throw it away, could indicate a serious error in the code. Even if it's not an error, it is at best a waste of resources.

Even assigning null to a variable is a dead store if the variable is not subsequently used. Assigning null as a hint to the garbage collector used to be common practice, but is no longer needed and such code should be eliminated.

Noncompliant Code Example

public void pow(int a, int b) {
  if(b == 0) {
    return 0;
  }
  int x = a;
  for(int i= 1, i < b, i++) {
    x = x * a;  //Dead store because the last return statement should return x instead of returning a
  }
  return a;
}

Compliant Solution

public void pow(int a, int b) {
  if(b == 0) {
    return 0;
  }
  int x = a;
  for(int i= 1, i < b, i++) {
    x = x * a;
  }
  return x;
}
5.equals方法左右兩邊的數據類型必須保持一致,例如:不能左邊是int,右邊是String

Comparisons of dissimilar types will always return false. The comparison and all its dependent code can simply be removed. This includes:

  • comparing an object with null
  • comparing an object with an unrelated primitive (E.G. a string with an int)
  • comparing unrelated classes
  • comparing an unrelated class and interface
  • comparing unrelated interface types
  • comparing an array to a non-array
  • comparing two arrays

Specifically in the case of arrays, since arrays don't override Object.equals(), calling equals on two arrays is the same as comparing their addresses. This means that array1.equals(array2) is equivalent toarray1==array2.

However, some developers might expect Array.equals(Object obj) to do more than a simple memory address comparison, comparing for instance the size and content of the two arrays. Instead, the == operator orArrays.equals(array1, array2) should always be used with arrays.

Noncompliant Code Example

interface KitchenTool { ... };
interface Plant {...}

public class Spatula implements KitchenTool { ... }
public class Tree implements Plant { ...}
//...

Spatula spatula = new Spatula();
KitchenTool tool = spatula;
KitchenTool [] tools = {tool};

Tree tree = new Tree();
Plant plant = tree;
Tree [] trees = {tree};


if (spatula.equals(tree)) { // Noncompliant; unrelated classes
  // ...
}
else if (spatula.equals(plant)) { // Noncompliant; unrelated class and interface
  // ...
}
else if (tool.equals(plant)) { // Noncompliant; unrelated interfaces
  // ...
}
else if (tool.equals(tools)) { // Noncompliant; array & non-array
  // ...
}
else if (trees.equals(tools)) {  // Noncompliant; incompatible arrays
  // ...
}
else if (tree.equals(null)) {  // Noncompliant
  // ...
}
6.equals方法推薦把常量放左邊,變量放右邊

It is preferable to place string literals on the left-hand side of an equals() or equalsIgnoreCase() method call.

This prevents null pointer exceptions from being raised, as a string literal can never be null by definition.

Noncompliant Code Example

String myString = null;

System.out.println("Equal? " + myString.equals("foo"));                        // Noncompliant; will raise a NPE
System.out.println("Equal? " + (myString != null && myString.equals("foo")));  // Noncompliant; null check could be removed

Compliant Solution

System.out.println("Equal?" + "foo".equals(myString));                         // properly deals with the null case
7.方法入參需要進行賦值操作的時候推薦用新的變量

While it is technically correct to assign to parameters from within method bodies, it is typically done in error, with the intent to assign a parameter value to a field of the same name, (and this was forgotten).

If it is done on purpose, a better course would be to use temporary variables to store intermediate results. Allowing parameters to be assigned to also reduces code readability because developers won't be able to tell whether the original parameter or some temporary variable is being accessed without going through the whole method. Moreover, some developers might also expect assignments of method parameters to be visible to callers, which is not the case, and this lack of visibility could confuse them. Instead, all parameters, caught exceptions, and foreach parameters should be treated as final.

Noncompliant Code Example

class MyClass {
  public String name;

  public MyClass(String name) {
    name = name;                    // Noncompliant - useless identity assignment
  }

  public int add(int a, int b) {
    a = a + b;                      // Noncompliant

    /* additional logic */

    return a;                       // Seems like the parameter is returned as is, what is the point?
  }

  public static void main(String[] args) {
    MyClass foo = new MyClass();
    int a = 40;
    int b = 2;
    foo.add(a, b);                  // Variable "a" will still hold 40 after this call
  }
}

Compliant Solution

class MyClass {
  public String name;

  public MyClass(String name) {
    this.name = name;               // Compliant
  }

  public int add(int a, int b) {
    return a + b;                   // Compliant
  }

  public static void main(String[] args) {
    MyClass foo = new MyClass();
    int a = 40;
    int b = 2;
    foo.add(a, b);
  }
}
8.去掉多餘的分號

Empty statements, i.e. ;, are usually introduced by mistake, for example because:

  • It was meant to be replaced by an actual statement, but this was forgotten.
  • There was a typo which lead the semicolon to be doubled, i.e. ;;.

Noncompliant Code Example

void doSomething() {
  ;                                                       // Noncompliant - was used as a kind of TODO marker
}

void doSomethingElse() {
  System.out.println("Hello, world!");;                     // Noncompliant - double ;
  ...
  for (int i = 0; i < 3; System.out.println(i), i++);       // Noncompliant - Rarely, they are used on purpose as the body of a loop. It is a bad practice to have side-effects outside of the loop body
  ...
}

Compliant Solution

void doSomething() {}

void doSomethingElse() {
  System.out.println("Hello, world!");
  ...
  for (int i = 0; i < 3; i++){
    System.out.println(i);
  }
  ...
}
9.不推薦用+"",老老實實用.toString()

"Boxing" is the process of putting a primitive value into a primitive-wrapper object. When that's done purely to use the wrapper class' toString method, it's a waste of memory and cycles because those methods arestatic, and can therefore be used without a class instance. Similarly, using the static method valueOf in the primitive-wrapper classes with a non-String argument should be avoided, as should concatenating empty string "" to a primitive.

Noncompliant Code Example

int myInt = 4;
String myIntString = new Integer(myInt).toString(); // Noncompliant; creates & discards an Integer object
myIntString = Integer.valueOf(myInt).toString(); // Noncompliant
myIntString = 4 + "";  // Noncompliant

Compliant Solution

int myInt = 4;
String myIntString = Integer.toString(myInt);
10.不要隨便拋個運行時異常,走點心,用自己定義的異常

Using such generic exceptions as ErrorRuntimeExceptionThrowable, and Exception prevents calling methods from handling true, system-generated exceptions differently than application-generated errors.

Noncompliant Code Example

public void foo(String bar) throws Throwable {  // Noncompliant
  throw new RuntimeException("My Message");     // Noncompliant
}

Compliant Solution

public void foo(String bar) {
  throw new MyOwnRuntimeException("My Message");
}

Exceptions

Generic exceptions in the signatures of overriding methods are ignored.

@Override
public void myMethod() throws Exception {...}
11.indexOf()方法針對字符char操作,不推薦對String操作,所以不能用雙引號“”,推薦用單引號''

An indexOf or lastIndexOf call with a single letter String can be made more performant by switching to a call with a char argument.

Noncompliant Code Example

String myStr = "Hello World";
// ...
int pos = myStr.indexOf("W");  // Noncompliant
// ...
int otherPos = myStr.lastIndexOf("r"); // Noncompliant
// ...

Compliant Solution

String myStr = "Hello World";
// ...
int pos = myStr.indexOf('W');
// ...
int otherPos = myStr.lastIndexOf('r');
// ...
12.StringBuilder大部分情況想比StringBuffer好用,性能高。單線程的時候就用StringBuilder就行了

Early classes of the Java API, such as VectorHashtable and StringBuffer, were synchronized to make them thread-safe. Unfortunately, synchronization has a big negative impact on performance, even when using these collections from a single thread.

It is better to use their new unsynchronized replacements:

  • ArrayList or LinkedList instead of Vector
  • Deque instead of Stack
  • HashMap instead of Hashtable
  • StringBuilder instead of StringBuffer

Noncompliant Code Example

Vector cats = new Vector();

Compliant Solution

ArrayList cats = new ArrayList();

Exceptions

Use of those synchronized classes is ignored in the signatures of overriding methods.

@Override
public Vector getCats() {...}
13.cookie必須setSercure(true)

The "secure" attribute prevents cookies from being sent over plaintext connections such as HTTP, where they would be easily eavesdropped upon. Instead, cookies with the secure attribute are only sent over encrypted HTTPS connections.

Noncompliant Code Example

Cookie c = new Cookie(SECRET, secret);  // Noncompliant; cookie is not secure
response.addCookie(c);

Compliant Solution

Cookie c = new Cookie(SECRET, secret);
c.setSecure(true);
response.addCookie(c);
14.推薦把內容複雜的常量變得可配置化,就是將它放在常量類裏進行統一管理,或者環境變量

Hardcoding an IP address into source code is a bad idea for several reasons:

  • a recompile is required if the address changes
  • it forces the same address to be used in every environment (dev, sys, qa, prod)
  • it places the responsibility of setting the value to use in production on the shoulders of the developer
  • it allows attackers to decompile the code and thereby discover a potentially sensitive address

Noncompliant Code Example

String ip = "127.0.0.1";
Socket socket = new Socket(ip, 6667);

Compliant Solution

String ip = System.getProperty("myapplication.ip");
Socket socket = new Socket(ip, 6667);

See


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章