Java에서 최종 키워드를 사용하면 성능이 향상됩니까?


347

자바에서는 final키워드를 사용할 수있는 곳이 많지만 그 용도는 드물다.

예를 들면 다음과 같습니다.

String str = "abc";
System.out.println(str);

위의 경우에는 str가능 final하지만 일반적으로 해제되어 있습니다.

메서드를 재정의하지 않을 때는 final 키워드를 사용할 수 있습니다. 상속되지 않는 클래스의 경우와 유사합니다.

이러한 경우 중 하나 또는 모두에 최종 키워드를 사용하면 실제로 실적이 향상됩니까? 그렇다면 어떻게? 설명 해주십시오. 제대로 사용하는 final것이 실제로 성능에 중요한 경우, Java 프로그래머는 키워드를 최대한 활용하기 위해 어떤 습관을 개발해야합니까?


나는 그렇게 생각하지 않습니다. 메소드 디스패치 (call site caching and ...)는 정적 유형 언어가 아닌 동적 언어의 문제입니다.
Jahan

검토 목적으로 사용되는 PMD 도구 (이클립스 플러그인)를 실행하면 위와 같이 변수를 변경하는 것이 좋습니다. 그러나 나는 그 개념을 이해하지 못했습니다. 정말 성능이 너무 좋아 ??
Abhishek Jain

5
나는 이것이 전형적인 시험 문제라고 생각했다. final 성능에 영향을 미친다 것을 기억합니다 . IIRC 최종 클래스는 하위 클래스화할 수 없기 때문에 어떤 방식 으로든 JRE에 의해 최적화 될 수 있습니다.
Kawu

나는 실제로 이것을 테스트했다. 모두의 JVM에 나는 지역 변수에 대한 최종은의 사용을 테스트 성능을 향상 (약간 있지만, 그럼에도 불구하고 유틸리티 메소드의 요인이 될 수 있습니다.) 소스 코드는 아래 답변에 있습니다.
rustyx

1
"조기 최적화는 모든 악의 근원"입니다. 컴파일러가 작동하게하십시오. 읽기 쉽고 주석이 달린 코드를 작성하십시오. 항상 최선의 선택입니다!
kaiser

답변:


285

보통은 아닙니다. 가상 메소드의 경우 HotSpot은 메소드가 실제로 대체 되었는지 여부를 추적하고 메소드가 대체 되지 않은 것으로 가정 하여 메소드를 대체하는 클래스를로드 할 때까지 인라인과 같은 최적화를 수행 할 수 있습니다. 이러한 최적화를 취소 (또는 부분적으로 취소) 할 수 있습니다.

(물론 이것은 핫스팟을 사용한다고 가정하지만 가장 일반적인 JVM이므로 ...)

내 생각 final에는 성능상의 이유보다는 명확한 디자인과 가독성을 기반으로 사용해야합니다 . 성능상의 이유로 변경하려는 경우 가장 명확한 코드를 구부리기 전에 적절한 측정을 수행해야합니다. 이렇게하면 추가 성능이 가독성 / 디자인의 가치가 없는지 여부를 결정할 수 있습니다. (내 경험상 YMMV는 거의 가치가 없습니다.)

편집 : 최종 필드가 언급되었으므로 명확한 디자인 측면에서 종종 좋은 아이디어라는 사실을 제기하는 것이 좋습니다. 또한 스레드 간 가시성 측면에서 보장 된 동작을 변경합니다. 생성자가 완료된 후 최종 필드는 다른 스레드에서 즉시 볼 수 있습니다. final조쉬 블로흐 (Josh Bloch)의 "상속을위한 디자인 또는 금지"규칙을지지하는 사람으로서 나는 아마도 내 경험에서 가장 일반적으로 사용 되는 것 같다 final.


1
@Abhishek : 특히 무엇에 대해? 가장 중요한 점은 마지막 점입니다. 거의 확실하지 않을 것입니다.
Jon Skeet

9
@Abishek : final일반적으로 코드를 이해하기 쉽고 버그를 찾는 데 도움이되기 때문에 일반적으로 권장됩니다 (프로그래머의 의도를 명확하게하기 때문에). PMD final는 성능 문제가 아닌 이러한 스타일 문제로 인해 사용하는 것이 좋습니다 .
sleske

3
@Abhishek : 많은 것이 JVM에 따라 다를 수 있으며 문맥의 미묘한 측면에 의존 할 수 있습니다. 예를 들어, HotSpot 서버 JVM은 적절한 경우 빠른 유형 검사를 통해 한 클래스에서 재정의되는 경우 가상 메소드를 계속 인라인 할 수 있다고 생각합니다 . 그러나 세부 사항은 고정하기가 어렵고 릴리스간에 변경 될 수 있습니다.
Jon Skeet

5
여기서는 Effective Java, 2nd Edition, Item 15, Minimize mutability :을 인용하겠습니다 Immutable classes are easier to design, implement, and use than mutable classes. They are less prone to error and are more secure.. 게다가 An immutable object can be in exactly one state, the state in which it was created.Mutable objects, on the other hand, can have arbitrarily complex state spaces.. 내 개인적인 경험에서 키워드를 사용하면 final코드를 "최적화"하는 것이 아니라 불변성에 의존하려는 개발자의 의도를 강조해야합니다. 이 장을 읽어 보시길 권합니다.
Louis F.

2
다른 답변에 따르면 final변수에 키워드 를 사용하면 바이트 코드의 양이 줄어들어 성능에 영향을 줄 수 있습니다.
Julien Kronegg

86

짧은 대답 : 걱정하지 마십시오!

긴 대답 :

최종 지역 변수 에 대해 이야기 할 때 키워드를 사용 final하면 컴파일러가 코드를 정적으로 최적화하는 데 도움 이되고 결과적으로 코드가 더 빨라질 수 있습니다. 예를 a + b들어 아래 예제 의 마지막 문자열 은 컴파일 타임에 정적으로 연결됩니다.

public class FinalTest {

    public static final int N_ITERATIONS = 1000000;

    public static String testFinal() {
        final String a = "a";
        final String b = "b";
        return a + b;
    }

    public static String testNonFinal() {
        String a = "a";
        String b = "b";
        return a + b;
    }

    public static void main(String[] args) {
        long tStart, tElapsed;

        tStart = System.currentTimeMillis();
        for (int i = 0; i < N_ITERATIONS; i++)
            testFinal();
        tElapsed = System.currentTimeMillis() - tStart;
        System.out.println("Method with finals took " + tElapsed + " ms");

        tStart = System.currentTimeMillis();
        for (int i = 0; i < N_ITERATIONS; i++)
            testNonFinal();
        tElapsed = System.currentTimeMillis() - tStart;
        System.out.println("Method without finals took " + tElapsed + " ms");

    }

}

결과?

Method with finals took 5 ms
Method without finals took 273 ms

Java Hotspot VM 1.7.0_45-b18에서 테스트되었습니다.

실제 성능이 얼마나 향상 되었습니까? 감히 말하지 않습니다. 대부분의 경우, 아마도 문자열 연결을 피하기 때문에이 합성 테스트에서 ~ 270 나노초 (아마도 드물지만)이지만 고도로 최적화 된 유틸리티 코드에서는 한 가지 요인 있습니다. 어쨌든 원래 질문에 대한 대답은 그렇습니다. 성능을 향상시킬 수는 있지만 조금 이라도 좋습니다 .

컴파일 타임의 이점을 제외하고는 키워드를 사용하면 final실적에 상당한 영향을 미친다는 증거를 찾을 수 없었 습니다.


2
두 경우를 100 번 테스트하기 위해 코드를 약간 다시 작성했습니다. 결국 최종의 평균 시간은 비 최종의 경우 0ms와 9ms입니다. 반복 횟수를 10M로 늘리면 평균이 0ms와 75ms로 설정됩니다. 그러나 비 결승에 대한 최상의 실행은 0ms였습니다. 어쩌면 VM 감지 결과가 그냥 버려지는 것입니까? 나는 모르지만 final을 사용하면 큰 차이가 있습니다.
Casper Færgemand

5
결함 테스트. 이전 테스트는 JVM을 예열하고 이후 테스트 호출에 도움이됩니다. 테스트를 재정렬하고 어떻게되는지 확인하십시오. 고유 한 JVM 인스턴스에서 각 테스트를 실행해야합니다.
Steve Kuo

16
테스트에 결함이 없으며 워밍업이 고려되었습니다. 두 번째 테스트는 더 빠르지 않고 더 느립니다. 예열이 없으면 두 번째 테스트는 더 느리게 진행됩니다.
rustyx

6
testFinal ()에서는 최종 문자열 및 문자열 리터럴 연결의 재 컴파일이 컴파일 타임에 평가되므로 문자열 풀에서 항상 동일한 객체를 반환했습니다. testNonFinal ()은 새로운 객체를 반환 할 때마다 속도의 차이를 설명합니다.
anber

4
시나리오가 비현실적이라고 생각하는 이유는 무엇입니까? String연결은 추가하는 것보다 훨씬 비용이 많이 드는 작업 Integers입니다. 정적으로 (가능한 경우) 정적으로하는 것이 더 효율적입니다. 그것이 바로 테스트 결과입니다.
rustyx

62

예, 그럴 수 있습니다. final이 성능을 향상시킬 수있는 인스턴스는 다음과 같습니다.

조건부 컴파일 은 특정 조건에 따라 코드 줄이 클래스 파일로 컴파일되지 않는 기술입니다. 프로덕션 빌드에서 수많은 디버깅 코드를 제거하는 데 사용할 수 있습니다.

다음을 고려하세요:

public class ConditionalCompile {

  private final static boolean doSomething= false;

    if (doSomething) {
       // do first part. 
    }

    if (doSomething) {
     // do second part. 
    }

    if (doSomething) {     
      // do third part. 
    }

    if (doSomething) {
    // do finalization part. 
    }
}

doSomething 속성을 최종 속성으로 변환하여 컴파일러에게 doSomething이 표시 될 때마다 컴파일 타임 대체 규칙에 따라 false로 대체해야한다고 컴파일러에 알 렸습니다. 컴파일러의 첫 번째 패스는 코드를 다음 과 같이 변경합니다 .

public class ConditionalCompile {

  private final static boolean doSomething= false;

    if (false){
       // do first part. 
    }

    if (false){
     // do second part. 
    }

    if (false){
      // do third part. 
    }

    if (false){
    // do finalization part. 

    }
}

이 작업이 완료되면 컴파일러는 다시 살펴보고 코드에 도달 할 수없는 명령문이 있음을 확인합니다. 최고 품질의 컴파일러로 작업하기 때문에 도달 할 수없는 모든 바이트 코드를 좋아하지 않습니다. 그래서 그것들을 제거하고 결국 이것으로 끝납니다.

public class ConditionalCompile {


  private final static boolean doSomething= false;

  public static void someMethodBetter( ) {

    // do first part. 

    // do second part. 

    // do third part. 

    // do finalization part. 

  }
}

따라서 과도한 코드 또는 불필요한 조건부 검사가 줄어 듭니다.

편집 : 예를 들어 다음 코드를 보자.

public class Test {
    public static final void main(String[] args) {
        boolean x = false;
        if (x) {
            System.out.println("x");
        }
        final boolean y = false;
        if (y) {
            System.out.println("y");
        }
        if (false) {
            System.out.println("z");
        }
    }
}

Java 8로이 코드를 컴파일하고 디 컴파일 javap -c Test.class하면 다음 과 같은 결과 를 얻습니다.

public class Test {
  public Test();
    Code:
       0: aload_0
       1: invokespecial #8                  // Method java/lang/Object."<init>":()V
       4: return

  public static final void main(java.lang.String[]);
    Code:
       0: iconst_0
       1: istore_1
       2: iload_1
       3: ifeq          14
       6: getstatic     #16                 // Field java/lang/System.out:Ljava/io/PrintStream;
       9: ldc           #22                 // String x
      11: invokevirtual #24                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      14: iconst_0
      15: istore_2
      16: return
}

컴파일 된 코드에는 비 최종 변수 만 포함되어 x있습니다. 이로 인해 최종 변수가 최소한이 간단한 경우 성능에 영향을 미치게됩니다.


1
@ ŁukaszLech 나는 Oreilly 책 : Hardcore Java에서 마지막 키워드에 관한 장에서 이것을 배웠습니다.
mel3kings

15
이것은 컴파일 타임에서의 최적화에 대해 이야기합니다. 개발자가 컴파일 타임에 최종 부울 변수의 값을 알고 있음을 의미합니다 .IF 조건이 필요하지 않고이 조건을 충족시키지 않는 시나리오의 경우 첫 번째 블록이 작성되는 시점의 요점은 무엇입니까? 어떤 의미? 내 의견으로는, 이것이 성능을 향상 시키더라도, 이것은 처음에는 잘못된 코드이며 컴파일러에 책임을 넘기지 않고 개발자가 직접 최적화 할 수 있으며, 질문은 주로 final이 사용되는 일반적인 코드의 성능 향상에 대해 묻습니다. 프로그래밍 방식으로 이해합니다.
Bhavesh Agarwal

7
이 점은 mel3kings에서 설명한대로 디버깅 명령문을 추가하는 것입니다. 프로덕션 빌드 전에 변수를 뒤집거나 배포 스크립트에서 변수를 구성하여 배포가 생성 될 때 해당 코드를 모두 자동으로 제거 할 수 있습니다.
Adam


16

아무도 실제로 약간의 차이가 있음을 증명하기 위해 디 컴파일 된 실제 코드를 게시하지 않은 것에 놀랐습니다.

참고로이에 대해 테스트 된 javac버전 8, 910.

이 방법을 가정하십시오.

public static int test() {
    /* final */ Object left = new Object();
    Object right = new Object();

    return left.hashCode() + right.hashCode();
}

이 코드를 그대로 컴파일하면 존재 했을 때와 정확히 동일한 바이트 코드가 생성 됩니다 final( final Object left = new Object();).

그러나 이것은 :

public static int test() {
    /* final */ int left = 11;
    int right = 12;
    return left + right;
}

생산 :

   0: bipush        11
   2: istore_0
   3: bipush        12
   5: istore_1
   6: iload_0
   7: iload_1
   8: iadd
   9: ireturn

final현재 상태로 두면 다음이 생성됩니다.

   0: bipush        12
   2: istore_1
   3: bipush        11
   5: iload_1
   6: iadd
   7: ireturn

컴파일 타임 상수가있는 경우 코드는 거의 자명하지 않으며 피연산자 스택에 직접로드됩니다 (이전 예제와 같은 로컬 변수 배열에는 저장되지 않음 bipush 12; istore_0; iload_0)-일종의 의미가 있습니다. 아무도 그것을 바꿀 수 없기 때문에.

반면에 두 번째 경우 컴파일러가 생성하지 않는 이유는 istore_0 ... iload_0슬롯 0을 사용하는 것과는 다릅니다 (변수 배열을 이런 식으로 축소 할 수는 있지만 일부 내부 세부 정보가 누락되어있을 수는 없습니다) 확실히 말해줘)

작은 최적화 방법을 고려할 때 이러한 최적화를보고 놀랐습니다 javac. 우리는 항상 사용해야 final합니까? 나는 심지어 JMH테스트 를 작성하지 않을 것입니다 (처음에는 원했습니다), diff가 ns(가능하면 캡처 될 수 있는) 순서대로 있다고 확신합니다 . 이것이 문제가 될 수있는 유일한 장소는 크기 때문에 메소드를 인라인 할 수없는 경우입니다 (선언 final하면 해당 크기가 몇 바이트 줄어 듭니다).

final해결해야 할 두 가지가 더 있습니다. 첫째, 방법이 final( JIT관점에서) 있을 때 , 그러한 방법은 단형 적 이며- 이 방법이 가장 사랑받는 방법 입니다 JVM.

그런 다음 final모든 생성자에서 설정해야하는 인스턴스 변수가 있습니다. 여기에서 약간 터치하고로 정확하게 지정된대로 올바르게 게시 된 참조를 보장하므로 중요 합니다 JLS.


디버그 옵션 ()과 함께 Java 8 (JDK 1.8.0_162)을 사용하여 코드를 컴파일하고을 javac -g FinalTest.java사용하여 코드를 디 컴파일 javap -c FinalTest.class하고 동일한 결과를 얻지 못했습니다 (with final int left=12, I got bipush 11; istore_0; bipush 12; istore_1; bipush 11; iload_1; iadd; ireturn). 따라서 생성 된 바이트 코드는 많은 요인에 따라 달라지며 final성능에 영향을 미치는지 여부를 말하기가 어렵습니다 . 그러나 바이트 코드가 다르면 약간의 성능 차이가있을 수 있습니다.
Julien Kronegg


13

실제로 두 가지 (적어도) 다른 경우에 대해 묻습니다.

  1. final 지역 변수
  2. final 메소드 / 클래스

Jon Skeet은 이미 2)로 답변했습니다. 약 1) :

나는 그것이 차이를 만들지 않는다고 생각합니다. 로컬 변수의 경우 컴파일러는 변수가 최종 변수인지 여부를 추론 할 수 있습니다 (단순히 두 번 이상 지정되었는지 확인하여). 따라서 컴파일러가 한 번만 할당 된 변수를 최적화하려는 경우 변수가 실제로 선언되었는지 여부에 관계없이 그렇게 할 수 있습니다 final.

final 보호 / 공공 클래스 필드에 차이를 만들 있습니다. 필드가 다른 클래스 (로드되지 않았을 수도 있음)에서 발생할 수 있으므로 필드가 두 번 이상 설정되어 있는지 확인하기가 매우 어렵습니다. 그러나 JVM조차도 Jon이 설명하는 기술을 사용할 수 있습니다 (낙관적으로 최적화하고 클래스가로드되면 필드를 변경하면 되돌립니다).

요약하면 성능에 도움이되는 이유는 없습니다. 따라서 이런 종류의 미세 최적화는 도움이되지 않습니다. 확인하기 위해 벤치마킹을 시도 할 수는 있지만 차이가 있을지 의심됩니다.

편집하다:

실제로 Timo Westkämper의 답변에 따르면 경우에 따라 수업 분야의 성능을 향상시킬 final 수 있습니다 . 나는 정정되었다.


컴파일러가 로컬 변수가 할당 된 횟수를 올바르게 확인할 수 있다고 생각하지 않습니다. 많은 할당이있는 if-then-else 구조체는 어떻습니까?
gyorgyabraham

1
@gyabraham : 지역 변수를로 선언하면 컴파일러는 이러한 경우를 이미 확인 final하여 두 번 할당하지 않도록합니다. 내가 볼 수있는 한, 동일한 검사 로직을 사용하여 변수가 될 수 있는지 여부를 확인할 수 있습니다 final.
sleske 2013

로컬 변수의 최종성은 바이트 코드로 표현되지 않으므로 JVM은 최종 변수를 알지 못합니다
Steve Kuo

1
@SteveKuo : 바이트 코드로 표현되지 않더라도 javac더 잘 최적화하는 데 도움 이 될 수 있습니다 . 그러나 이것은 단지 추측 일뿐입니다.
sleske 2016 년

1
컴파일러는 로컬 변수가 정확히 한 번만 할당되었는지 알 수 있지만 실제로는 (오류 확인 이외) 그렇지 않습니다. 반면에 final변수가 기본 유형 또는 유형 String이고 질문의 예에서와 같이 컴파일 타임 상수로 즉시 할당 되는 경우 변수는 사양에 따라 컴파일 타임 상수이므로 컴파일러 인라인 해야합니다 . 그러나 대부분의 사용 사례에서 코드는 다르게 보일 수 있지만 상수가 성능 측면에서 로컬 변수에서 인라인되거나 읽혀 지는지 여부는 여전히 차이가 없습니다.
Holger

6

참고 : 자바 전문가가 아닙니다

내 Java를 올바르게 기억하면 최종 키워드를 사용하여 성능을 향상시킬 수있는 방법이 거의 없습니다. 나는 항상 "좋은 코드"-디자인과 가독성을 위해 존재하는 것으로 알고 있습니다.


1

나는 전문가가 아니지만 final키워드를 덮어 쓰지 않고 변수를 남겨 두지 않으면 클래스 또는 메소드에 키워드를 추가해야한다고 가정합니다 . 그러한 것들을 최적화하는 방법이 있다면 컴파일러가 그렇게 할 것입니다.


1

실제로 일부 OpenGL 관련 코드를 테스트하는 동안 개인 필드에서 최종 수정자를 사용 하면 성능 이 저하 될있습니다 . 테스트 한 수업의 시작은 다음과 같습니다.

public class ShaderInput {

    private /* final */ float[] input;
    private /* final */ int[] strides;


    public ShaderInput()
    {
        this.input = new float[10];
        this.strides = new int[] { 0, 4, 8 };
    }


    public ShaderInput x(int stride, float val)
    {
        input[strides[stride] + 0] = val;
        return this;
    }

    // more stuff ...

그리고 이것은 ShaderInput 클래스 중 다양한 대안의 성능을 테스트하는 데 사용한 방법입니다.

public static void test4()
{
    int arraySize = 10;
    float[] fb = new float[arraySize];
    for (int i = 0; i < arraySize; i++) {
        fb[i] = random.nextFloat();
    }
    int times = 1000000000;
    for (int i = 0; i < 10; ++i) {
        floatVectorTest(times, fb);
        arrayCopyTest(times, fb);
        shaderInputTest(times, fb);
        directFloatArrayTest(times, fb);
        System.out.println();
        System.gc();
    }
}

3 번 반복 한 후 VM이 예열 된 후 최종 키워드 없이 일관 되게이 수치 얻었습니다 .

Simple array copy took   : 02.64
System.arrayCopy took    : 03.20
ShaderInput took         : 00.77
Unsafe float array took  : 05.47

으로 최종 키워드 :

Simple array copy took   : 02.66
System.arrayCopy took    : 03.20
ShaderInput took         : 02.59
Unsafe float array took  : 06.24

ShaderInput 테스트 수치를 참고하십시오.

필드를 공개 또는 비공개로 설정했는지는 중요하지 않았습니다.

덧붙여서, 몇 가지 더 당황스러운 것들이 있습니다. ShaderInput 클래스는 final 키워드를 사용하더라도 다른 모든 변형보다 성능이 뛰어납니다. 이것은 기본적으로 float 배열을 감싸는 클래스이며 다른 테스트 는 배열을 직접 조작합니다. 이것을 알아 내야합니다. ShaderInput의 유창한 인터페이스와 관련이있을 수 있습니다.

또한 System.arrayCopy는 실제로 작은 배열의 경우 for 루프에서 단순히 한 배열에서 다른 배열로 요소를 복사하는 것보다 다소 느립니다. 그리고 sun.misc.Unsafe (및 여기에 표시되지 않은 직접 java.nio.FloatBuffer)를 사용하면 아주 작습니다.


1
매개 변수를 최종으로 설정하는 것을 잊었습니다. <pre> <code> public ShaderInput x (최종 정수 보폭, 최종 부동 소수점) {input [strides [stride] + 0] = val; 이것을 돌려줍니다; } </ code> </ pre> 내 경험에 따르면, 변수 또는 필드 파이널을 수행하면 실제로 성능이 향상 될 수 있습니다.
Anticro

1
아, 그리고 다른 것들도 최종적으로 만듭니다 : <pre> <code> final int arraySize = 10; 최종 float [] fb = 새로운 float [arraySize]; for (int i = 0; i <arraySize; i ++) {fb [i] = random.nextFloat (); } 최종 int 시간 = 1000000000; for (int i = 0; i <10; ++ i) {floatVectorTest (times, fb); arrayCopyTest (시간, fb); shaderInputTest (times, fb); directFloatArrayTest (times, fb); System.out.println (); System.gc (); } </ code> </ pre>
Anticro

1

최종 (적어도 멤버 변수 및 매개 변수의 경우)은 인간에게는 더 많으며 기계에 대한 것입니다.

가능하면 변수를 최종적으로 만드는 것이 좋습니다. Java가 기본적으로 "변수"를 최종적으로 만들고 변경을 허용하는 "Mutable"키워드가 있었으면 좋겠습니다. 불변의 클래스는 훨씬 나은 스레드 코드로 이어지고 각 멤버 앞에 "최종"이있는 클래스를 보는 것만으로도 불변의 것으로 빠르게 표시됩니다.

또 다른 경우-@ NonNull / @ Nullable 주석을 사용하도록 많은 코드를 변환했습니다 (메소드 매개 변수가 null이 아니어야한다고 말할 수 있습니다. IDE는 태그가없는 변수를 전달하는 모든 곳에서 경고 할 수 있습니다 @ NonNull-모든 것이 우스운 정도로 퍼집니다). 다른 곳에 재 할당되지 않는다는 것을 알고 있으므로 final 태그가 붙었을 때 멤버 변수 또는 매개 변수가 null 일 수 없다는 것을 증명하는 것이 훨씬 쉽습니다.

내 제안은 기본적으로 멤버 및 매개 변수에 final을 적용하는 습관을들이는 것입니다. 단지 몇 자이지만 코딩 스타일을 개선하는 데 도움이 될 것입니다.

메소드 나 클래스에 대한 결말은 또 다른 개념으로, 이는 매우 유효한 형태의 재사용을 허용하지 않으며 독자에게 많은 것을 알려주지 않기 때문입니다. 가장 잘 사용하는 것은 아마도 String과 다른 내장 유형을 최종적으로 만든 방법 일 것이므로 모든 곳에서 일관된 동작에 의존 할 수 있습니다. 많은 버그를 예방했습니다 (문자열을 확장하는 것을 좋아했을 때도 있지만). 가능성)


0

다른 곳에서 언급했듯이, 지역 변수에 대한 '최종'및 멤버 변수에 대한 범위는 약간 적습니다.

'final'은 변수를 변경하지 않으려는 선언입니다 (예 : 변수는 변하지 않습니다!). 그런 다음 컴파일러는 자신의 제약 조건을 위반하면 불평함으로써 도움을 줄 수 있습니다.

식별자 (기본적으로 변수가 아닌 것을 '변수'라고 부를 수는 없습니다)가 최종적으로 Java 인 경우 Java가 더 나은 언어 였을 것이라는 감정을 공유하고 변수라고 명시 적으로 말하도록 요구했습니다. 그러나 말했지만, 일반적으로 초기화되고 할당되지 않은 로컬 변수에는 '최종'을 사용하지 않습니다. 너무 시끄러운 것 같습니다.

(멤버 변수에 final을 사용합니다)


-3

final로 선언 된 멤버는 최종 멤버가 아닌 멤버와 달리 프로그램에서 사용되지 않은 경우에도 가비지 콜렉터에서 관리하지 않으므로 메모리 관리가 잘못되어 성능 문제가 발생할 수 있기 때문에 프로그램 전체에서 사용할 수 있습니다.


2
이것은 어떤 종류의 말도 안됩니까? 왜 이런 생각이 든다고 생각하십니까?
J. Doe

-4

final 키워드는 Java에서 5 가지 방식으로 사용될 수 있습니다.

  1. 수업은 최종
  2. 참조 변수는 최종입니다
  3. 지역 변수가 최종입니다
  4. 방법은 최종입니다

클래스는 최종적입니다 : 클래스는 최종적이란 우리가 확장 할 수 없거나 상속이 불가능하다는 것을 의미합니다.

비슷하게 – 객체는 최종적입니다 : 언젠가 우리는 객체의 내부 상태를 수정하지 않기 때문에 객체를 최종 객체로 지정할 수 있습니다.

참조 변수가 최종적으로 만들어지면 다른 객체에 재 할당 할 수 없습니다. 그러나 필드가 최종이 아닌 한 객체의 내용을 변경할 수 있습니다


2
"객체가 최종적"이라는 것은 "개체는 불변이다"를 의미한다.
gyorgyabraham

6
당신 말이 맞지만 질문에 대답하지 않습니다. OP는 무엇을 final의미 하는지 묻지 않았지만 사용 final이 성능에 영향 을 미치는지 여부를 묻습니다 .
Honza Zidek
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.