자바 언어 관용구
1. 주기
중요한 루프에서는 루프 종료를 결정할 때 메서드 호출을 제거합니다.
예를 들면 다음과 같습니다.
for(int i=0; i<collection.size();i++){ ... }
다음으로 교체…
for(int i=0; n=collection.size();i<n;i++){...}
일반적으로 루프 인덱스와 관련되지 않은 항목을 루프 외부로 이동합니다.
for(int i=0; 터미널=x.length;i<terminal;i++){x[i] = x[i]/scaleA *scaleB;}
다음과 같아야 합니다.
이중 스케일 = scaleB*scaleA;for(int i=0; 터미널=x.length;i<terminal;i++){x[i] = x[i]/scale;}
2. 끈
문자열 연결 제거
긴 문자열을 생성할 때는 항상 String 대신 StringBuffter를 사용하세요.
StringBuffer 공간을 사전 할당 StringBuffer sb = new StringBuffer(5000);
3. 기본 데이터 유형
중요한 루프에서는 기본 데이터 유형을 사용합니다(int 데이터는 일반적으로 long/double 데이터보다 빠릅니다).
기본 데이터 유형(Boolean, Integer 등)의 래핑 클래스는 전달된 메소드 매개변수가 (기본 데이터 유형이 아닌) 객체에 대한 참조여야 할 때 주로 사용됩니다.
모든 상수 대수 표현식에 static final 수정자를 사용하여 상수를 더 쉽게 참조할 수 있도록 합니다(컴파일러는 상수 표현식을 미리 계산합니다).
4. 이상
예외는 예외를 던지고 catch 블록을 실행하는 데 비용이 많이 드는 단일 실제 오류 조건에만 사용됩니다(주로 예외를 생성할 때 스레드 스택의 스냅샷을 얻기 때문에).
조건이 실제로 예외인 경우에만 예외가 발생합니다. 예외를 발생시키려면 먼저 새 개체를 만듭니다.
Throwable 인터페이스의 생성자는 fillInStackTrace()라는 기본 메서드를 호출합니다. fillInStackTrace() 메서드는 스택을 확인하고 호출 추적 정보를 수집합니다.
예외가 발생할 때마다 처리 중에 새 개체가 생성되므로 VM은 호출 스택을 조정해야 합니다.
예외는 오류 처리에만 사용해야 하며 프로그램 흐름을 제어하는 데 사용해서는 안 됩니다.
각 메서드 호출에 대해 여러 try/catch 블록을 구현하는 대신 try/catch 블록에 여러 메서드 호출을 배치하여 컴파일러 및 런타임 최적화를 수행합니다.
try{ Some.method1(); //java1.4에서는 어려움 }catch(method1Exception e){ 예외 처리
1 // 이 코드를 최적화하려면 } try{ Some.method2(); //java1.4에서는 어려움 }catch(method2Exception e){ 예외 처리
2 // 이 코드를 최적화하려면 } try{ Some.method3(); //java1.4에서는 어려움 }catch(method3Exception e){ 예외 처리
3 // 이 코드를 최적화하려면
}
다음과 같이 작성되어야 합니다:
try{ Some.method1(); Some.method3(); //java1.4에서는 어려움 }catch(method1Exception e){ 예외 1 처리 }catch(method2Exception e){ 예외 2 처리 }catch( method3Exception e){ 예외 3 처리 }
5. 기준
이러한 모든 팁은 플랫폼과 가상 머신에 따라 다릅니다.
예: 일부 서블릿 컨테이너에서는 OutputStream을 통해 바이트를 출력하는 것이 더 빠릅니다.
2. 다른 컨테이너에서는 PrintWriter를 통해 문자를 출력하는 것이 더 빠릅니다.
이 팁은 가장 이식성이 뛰어난 권장 사항을 설명합니다.
플랫폼에서 가장 빠른 것이 무엇인지 결정하기 위해 일부 벤치마크를 실행해야 할 수도 있습니다.
6. new 키워드를 사용하지 않고 클래스 인스턴스 만들기
new 키워드를 사용하여 클래스의 인스턴스를 생성하면 생성자 체인의 모든 생성자가 자동으로 호출됩니다.
그러나 객체가 Cloneable 인터페이스를 구현하는 경우 해당 clone() 메서드를 호출할 수 있습니다. clone() 메서드는 클래스 생성자를 호출하지 않습니다.
Design Pattern을 사용할 때 Factory 모드를 사용하여 객체를 생성하는 경우 clone() 메서드를 사용하여 새로운 객체 인스턴스를 생성하는 것은 매우 간단합니다.
예를 들어 다음은 Factory 패턴의 일반적인 구현입니다.
공개 정적 크레딧 getNewCredit() { 새 크레딧() 반환 }
최적화 후:
private static Credit BaseCredit = new Credit(); public static Credit getNewCredit() { return (Credit) BaseCredit.clone();}
위의 아이디어는 배열 처리에도 유용합니다.
7. 비차단 I/O 사용
더 낮은 Java 버전의 JDK는 비차단 I/O API를 지원하지 않습니다. I/O 차단을 방지하기 위해 일부 응용 프로그램은 많은 수의 스레드를 생성합니다(더 나은 경우에는 버퍼 풀이 사용됩니다). 이 기술은 웹 서버, 견적 및 경매 애플리케이션 등과 같이 동시 I/O 스트림을 지원해야 하는 많은 애플리케이션에서 볼 수 있습니다. 그러나 Java 스레드를 생성하려면 상당한 오버헤드가 필요합니다.
JDK 1.4에는 비차단 I/O 라이브러리(java.nio)가 도입되었습니다. 애플리케이션에 이전 버전의 JDK가 필요한 경우 비차단 I/O를 지원하는 패키지가 있습니다.
8. 변수를 반복적으로 초기화하지 마십시오
기본적으로 클래스의 생성자를 호출할 때 Java는 변수를 특정 값으로 초기화합니다. 모든 객체는 null로 설정되고 정수 변수(byte, short, int, long)는 0으로 설정되고 float 및 double 변수는 0으로 설정됩니다. 0.0이면 논리값이 false로 설정됩니다.
클래스가 다른 클래스에서 파생될 때 특히 주의해야 합니다. 왜냐하면 new 키워드를 사용하여 객체를 생성하면 생성자 체인의 모든 생성자가 자동으로 호출되기 때문입니다.
9. 클래스의 최종 수정자를 지정해 보십시오.
final 수정자가 있는 클래스는 파생되지 않습니다. Java Core API에는 java.lang.String 등 final을 적용한 예가 많이 있습니다. String 클래스에 final을 지정하면 사람들이 length() 메서드를 재정의하는 것을 방지할 수 있습니다.
또한 클래스가 final로 지정되면 해당 클래스의 모든 메서드가 final이 됩니다. Java 컴파일러는 모든 최종 메소드를 인라인할 수 있는 기회를 찾습니다(이는 특정 컴파일러 구현에 따라 다름). 이를 통해 성능을 평균 50% 향상할 수 있습니다.
10. 가능하면 지역 변수를 사용하세요
메소드 호출 시 전달된 파라미터와 호출 시 생성된 임시 변수는 스택(Stack)에 저장되므로 속도가 더 빠릅니다. 정적 변수, 인스턴스 변수 등과 같은 다른 변수는 힙에 생성되며 속도가 느립니다. 또한 특정 컴파일러/JVM에 따라 지역 변수가 더욱 최적화될 수 있습니다. 가능한 경우 스택 변수 사용을 참조하세요.
11. 곱셈과 나눗셈
다음 코드를 고려해보세요.
for (val = 0; val < 100000; val +=5) { alterX = val * 8 myResult = val * 2;
최적화 후:
for (val = 0; val < 100000; val += 5) { alterX = val << 3 = val << 1;
수정된 코드는 더 이상 8을 곱하는 연산을 수행하지 않고 대신 3비트를 왼쪽으로 이동하는 동일한 연산을 사용합니다. 1비트의 왼쪽 시프트는 2를 곱하는 것과 같습니다. 따라서 1비트의 오른쪽 시프트 연산은 2로 나누는 것과 같습니다. Shift 연산은 빠르지만 코드를 이해하기 어렵게 만들 수 있으므로 주석을 추가하는 것이 가장 좋습니다.
private static Credit BaseCredit = new Credit(); public static Credit getNewCredit() {return (Credit) BaseCredit.clone();}