Sonar规范扫描Java代码暴露的问题

字符串和封装类型应使用 equals()进行比较

例如java.lang.Integer使用引用等于==!=,因为它不是比较实际值,而是比较内存中的位置。

String firstName = getFirstName(); // String overrides equals
String lastName = getLastName();

if (firstName == lastName) { ... }; // 即使字符串具有相同的值,也为false


方法参数,捕获的异常和foreach变量的初始值不应忽略

public void doTheThing(String str, int i, List<String> strings) {
 // str = Integer.toString(i); // 不符合规定
    
  String str1 = str	//在使用之前需要保存初始值
      
  for (String s : strings) {
    s = "hello world"; // Noncompliant
  }
}

"InterruptedException" should not be ignored

在代码中不应该忽略中断异常,只在日志中打印异常日志,就像“忽略”一样。抛出中断异常会清除线程的中断状态,因此如果异常处理不当,那么线程被中断的信息将会丢失。相反,中断应该被重新抛出——立即或者在清理方法的状态之后——或者应该通过调用Thread.interrupt()来重新中断线程,即使这是单线程的应用程序。任何其他的操作过程都有延迟线程关闭的风险,并且丢失了线程被中断的信息——线程很可能没有完成它的任务。

类似地,也应该传播ThreadDeath异常。根据它的JavaDoc:

如果ThreadDeath异常被一个方法捕获,那么它被重新抛出是很重要的,这样线程就会结束。

不符合要求的代码如下:


public void run () {
  try {
    while (true) {
      // do stuff
    }
  }catch (InterruptedException e) { // Noncompliant; logging is not enough
    LOGGER.log(Level.WARN, "Interrupted!", e);	// catch块中只是打印了异常日志,相当于忽略了这个异常。
  }
}

解决方案

//Compliant Solution
public void run () {
  try {
    while (true) {
      // do stuff
    }
  }catch (InterruptedException e) {
    LOGGER.log(Level.WARN, "Interrupted!", e);
    // 恢复中断状态
    Thread.currentThread().interrupt();
  }
}

枚举字段不应有public修饰的setter方法

enum通常被视为常量,但是enum带有public字段或public的setter方法的不仅是非常量的,而且还容易受到恶意代码的攻击。理想情况下,枚举字段应该用private修饰或者在构造器中赋值,但如果不可能,则应尽可能降低其可见性

反例

public enum Continent {

  NORTH_AMERICA (23, 24709000),
  // ...
  EUROPE (50, 39310000);

  public int countryCount;  // 不合理
  private int landMass;

  Continent(int countryCount, int landMass) {
    // ...
  }

  public void setLandMass(int landMass) {  // 不合理
    this.landMass = landMass;
  }

规范写法

public enum Continent {

  NORTH_AMERICA (23, 24709000),
  // ...
  EUROPE (50, 39310000);

  private int countryCount;
  private int landMass;

  public Continent(int countryCount, int landMass) {
    // ...
  }
    
  void setCountryCount(int countryCount){
      this.countryCount = countryCount;
  }
    
  public getCountryCount(){
      return countryCount;
  }
posted @ 2021-04-28 16:00  至安  阅读(1574)  评论(0编辑  收藏  举报