본문 바로가기

PMD

[한글화 시리즈-16] Optimization Rules

Optimization Rules

이 룰셋은 성능 향상을 위한 최적화 룰들을 포함한다.



LocalVariableCouldBeFinal

지역 변수가 한번만 할당된다면 final로 정의할 수 있다.

public class Bar {
  public void foo () {
    //이후 다시 설정되지 않는다면 final로 정의하자
    String a = "a"; 
    final String b = "b";
  }
}


MethodArgumentCouldBeFinal

전달인자가 전달된 이후 다시 할당되지 않는다면 final로 정의하자

public void foo (String param) {
  // 위의 인자가 다시 할당되지 않는다면 아래와 같이 정의하자
  // public void foo (final String param) {
}

AvoidInstantiatingObjectsInLoops

반복문 내에서 객체를 인스턴트화하지 말자.

public class Something {
  public static void main( String as[] ) {  
    for (int i = 0; i < 10; i++) {
      //가능하면 언제든지 이런 코드는 피하자, 많은 실행비용이 필요하다.
      Foo f = new Foo(); 
    }
  }
}

UseArrayListInsteadOfVector

Vector보다 ArrayList는 훨신 더 나은 Collection이다.

public class SimpleTest extends TestCase {
  public void testX() {
    Collection c = new Vector();
    // threadsafe문제만 아니라면 다음과 같이 만들자
    // Collection c = new ArrayList();
  }
}


SimplifyStartsWith

문자열의 길이가 1이라면 String.startsWith 보다 String.charAt(0)이 더 빠르다.

public class Foo {
  //한글자라면 아래의 방법이 사용하는 것이 더 빠르다.
  boolean checkIt(String x) {
    return x.startsWith("a");
  }

  boolean checkIt(String x) {
    return x.charAt(0) == 'a';
  }
}

UseStringBufferForStringAppends

문자열에 새로운 문자열을 더하는 연산은 +=를 사용하는 것보다 StringBuffer  또는 StringBuilder를 사용하는 것이 더 빠르다. 단 StringBuffer는 스레드 동기화(synchronized)되어 있어서 threadsafe는 보장하지만 StringBuilder보다는 느리다.

public class Foo {
  void bar() {
    String a;
    a = "foo";
    a += " bar";
    // 문자열의 다음과 같이 StringBuffer 또는 StringBuilder를 사용하자.
    // StringBuffer a = new StringBuffer("foo");
    // a.append(" bar);
  }
}


UseArraysAsList

객체의 배열(array)에서 List Collection으로 변환할 때 asList 메소드를 사용해야 한다. 이 메소드가 반복문을 사용해서 객체 하나하나를 복사하는 것보다 더욱 빠르게 수행될 수 있다.

public class Test {
  public void foo(Integer[] ints) {
    List l= new ArrayList(10);
    // 아래의 코드 모두 느리고 코드만 복잡하다.
    // 그냥 Arrays.asList(ints)를 이용하자.
    for (int i=0; i< 100; i++) {
      l.add(ints[i]);
    }
    for (int i=0; i< 100; i++) {
      l.add(a[i].toString()); 
    }
  }
}

AvoidArrayLoops

두개의 배열(array)들 사이에 데이터 복사는 한땀한땀 하지말고 그냥 System.arraycopy를 사용하자.

public class Test {
  public void bar() {
    int[] a = new int[10];
    int[] b = new int[10];
    for (int i=0;i<10;i++) {
      b[i]=a[i];
    }
    //그냥 다음과 같이 복사하자.
    System.arraycopy(a, 0, b, 0, a.length);
  }
}

UnnecessaryWrapperObjectCreation

변환 메소드는 직접적으로 호출하여 사용하자.

public int convert(String s) {
  int i, i2;

  i = Integer.valueOf(s).intValue();
  // 객체를 낭비하는 일이다. 아래와 같이 바로 변환 가능
  i = Integer.parseInt(s);

  i2 = Integer.valueOf(i).intValue(); 
  // 객체를 낭비하는 일이다. 아래와 같이 바로 변환 가능
  i2 = i; 

  String s3 = Integer.valueOf(i2).toString();
  // // 객체를 낭비하는 일이다. 아래와 같이 바로 변환 가능
  s3 = Integer.toString(i2);

  return i2;
}

AddEmptyString

숫자를 문자열로 변환할 경우 비어있는 문자열("")을 이용하는 것은 매우 비효율적이다. 

String s = "" + 123; //비효율적인 방식
String t = Integer.toString(456); //효율적인 방식

해당 URL: http://pmd.sourceforge.net/pmd-4.2.6/rules/optimizations.html