Java에서 루프 내부 또는 외부에서 변수를 선언하면 차이가 있습니까? [닫은]


13

가능한 중복 :
변수를 어디에서 선언합니까? 방법의 상단 또는 필요할 때?

Java에서 루프 내부 또는 외부에서 변수를 선언하면 차이가 있습니까?

이거

for(int i = 0; i < 1000; i++) {
   int temp = doSomething();
   someMethod(temp);
}

이것과 같습니까 (메모리 사용과 관련하여)?

int temp = 0;
for(int i = 0; i < 1000; i++) {
   temp = doSomething();
   someMethod(temp);
}

임시 변수가 예를 들어 ArrayList라면?

for(int i = 0; i < 1000; i++) {
   ArrayList<Integer> array = new ArrayList<Integer>();
   fillArray(array);
   // do something with the array
}

편집 : javap -c나는 다음과 같은 결과를 얻었다

루프 외부 변수 :

  public static void main(java.lang.String[]);
    Code:
       0: iconst_0      
       1: istore_1      
       2: iconst_0      
       3: istore_2      
       4: iload_2       
       5: sipush        1000
       8: if_icmpge     25
      11: invokestatic  #2                  // Method doSomething:()I
      14: istore_1      
      15: iload_1       
      16: invokestatic  #3                  // Method someMethod:(I)V
      19: iinc          2, 1
      22: goto          4
      25: return  

루프 내부 변수 :

  public static void main(java.lang.String[]);
    Code:
       0: iconst_0      
       1: istore_1      
       2: iload_1       
       3: sipush        1000
       6: if_icmpge     23
       9: invokestatic  #2                  // Method doSomething:()I
      12: istore_2      
      13: iload_2       
      14: invokestatic  #3                  // Method someMethod:(I)V
      17: iinc          1, 1
      20: goto          2
      23: return        

그리고 관심을 끌기 위해이 코드는 다음과 같습니다.

public class Test3 {
    public static void main(String[] args) {
        for(int i = 0; i< 1000; i++) {
            someMethod(doSomething());
        }   
    }
    private static int doSomething() {
        return 1;
    }
    private static void someMethod(int temp) {
        temp++;
    }
}

이것을 생성합니다 :

  public static void main(java.lang.String[]);
    Code:
       0: iconst_0      
       1: istore_1      
       2: iload_1       
       3: sipush        1000
       6: if_icmpge     21
       9: invokestatic  #2                  // Method doSomething:()I
      12: invokestatic  #3                  // Method someMethod:(I)V
      15: iinc          1, 1
      18: goto          2
      21: return   

그러나 최적화는 런타임에 발생합니다. 최적화 된 코드를 볼 수있는 방법이 있습니까? (오래 편집하다 죄송합니다)


1
나는 당신이 실제로 분해를 보았고 그것이 당신에게 무언가를 가르쳐주기를 바랍니다. 실제 Java 경험이있는 사람이 최적화 된 코드에 대한 최종 질문에 대답하기를 희망했지만 Stackoverflow에 특정 부분을 게시 할 수 있습니다. 매우 구체적인 질문 인 것 같습니다.
Joris Timmermans

예, 최적화 된 코드를 얻으려고 노력할 것입니다. (질문이 조금 바뀌어 편집에서 최적화 된 코드로 질문했습니다.)
Puckl

중복 된 링크가 끊어졌습니다. 이 질문을 독창적으로 만들 차례입니다.
Zon

답변:


4

이러한 대부분의 질문에 대한 일반적인 대답은 "어떻게 시도하고 알아 내지 않습니까?"입니다. Java에서는 아마도 생성 된 바이트 코드 (도구가 javap라고 생각)를 살펴보고 바이트 코드의 차이점이 변수를 선언하는 두 가지 방법 사이에 있는지 확인할 수 있습니다.

다음에 최적화 문제를 겪을 때 동일한 도구를 사용하여 컴파일러가 원하는 작업을 수행하는지 확인할 수 있으므로 코딩을 불필요하게 변경하지 않아도됩니다. 옵티마이 저가 자체적으로 잘 수행 할 때 스타일을 지정하거나 마지막 성능이 필요할 때 실제 조정을 찾습니다.


3

짧은 대답 : 아니오. 이 사이트 어딘가에 비슷한 질문이있었습니다. 생성 된 바이트 코드에 따라 눈에 띄는 차이는 없습니다. 필요할 때 선언하면 코드 줄이 줄어 듭니다.

허용되는 답변은 다음과 같습니다. /software//a/56590/43451


루프 내에서 새 객체를 만들 때 한 번만 만들 수있는 성능은 어떻습니까?
Bubblewrap

3
이 경우 분명히 성능과 메모리 패널티가 있습니다. 그러나 작전의 질문에
있어서는 그렇지 않다

1
링크가 끊어졌습니다.
Zon

1

개별 변수의 수준에는 효율성에 큰 차이가 없지만 1000 개의 루프와 1000 개의 변수가있는 함수가있는 경우 (나쁜 스타일을 암시하지는 않지만) 모든 변수의 모든 수명은 다음과 같습니다. 겹치지 않고 동일합니다. 이는 스택 크기 및 가비지 수집기에서 필요 이상으로 오래 유지 된 변수를 정리하는 기능에 영향을 줄 수 있습니다.

또한 변수에 가능한 가장 작은 범위를 제공하는 것이 훨씬 좋습니다. 사고를 예방합니다.


이것은 사실이 아닙니다. JVM 수준에서는 로컬 변수의 범위가 제한되어 있지 않습니다.
Michael Borgwardt

for (int i = ..)를 1000 번 쓰면 함수를 종료 할 때 스택에 1000 개의 다른 변수가 있음을 의미합니까?
ddyer

artima.com/insidejvm/ed2/jvm8.html 에 따르면 "예를 들어 Example3b의 i 및 j 로컬 변수와 같이 두 개의 로컬 변수가 겹치지 않는 범위가 제한된 경우 컴파일러는 동일한 배열 항목을 자유롭게 사용할 수 있습니다. 컴파일러는 이런 방식으로 스택 프레임의 크기를 자유롭게 최적화 할 수 있습니다.
ddyer

1
좋은 지적; 그러나 컴파일러 최적화에 대해 이야기하는 경우 컴파일러는 어휘 범위가 겹치지 만 겹치는 방식으로 사용 되지 않는 변수에 대해 로컬 변수 항목을 거의 쉽게 재사용 할 수 있습니다 .
Michael Borgwardt
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.