본문 바로가기
프로그래밍 언어/Java

[Java] 유효범위

by 까망 하르방 2021. 3. 4.
반응형

대규모 프로젝트에서는 코드가 길어지며 복잡해지면서 변수와 함수명이 여러 가지 이유로 이름 충돌.

이를 해결하기 위해서 고안된 것이 유효범위입니다. Scope라고도 부릅니다.

 

[무한 반복으로 빠지는 예시]

public class Main {

    static int i;
    static void a() {
        i = 0;
    }

    public static void main(String[] args) {
        for (i = 0; i < 5; i++) {
            a();
            System.out.println(i);
        }
    }
}

메소드 a()가 실행될 때 메소드 내부의 변수 i의 값이 반복문의 변수 i의 값을 덮어씌워

반복문이 호출될 때마다 변수 i의 값이 0이 되어 반복문은 무한 반복에 빠지게 된다.

이런 상황을 해결하기 위해서는 메소드 a의 내부변수 i의 이름이나 반복문의 변수 i의

이름을 다르게 로직을 고치는 방법이 있다.

하지만 로직이 매우 복잡하거나, 메소드 a()가 타인이 만든 것을 사용하는 것이라면

이름 변경을 함으로서 어떤 영향이 있을지 예측할 수 없다.

 

또 다른 방법이 유효범위를 이용하는 것입니다.

public class Main {
    static void a() {
        int i = 0;
    }

    public static void main(String[] args) {
        for (int i = 0; i < 5; i++) {
            a();
            System.out.println(i);
        }
    }
}

내부 변수의 값이 그 외부에 영향을 미치지 않는다는 것을 알 수 있습니다.

즉, 해당 메소드가 실행될 때 만들어지고, 그 메소드가 종료되면 삭제됩니다.

- 클래스 전역에서 접근 할 수 있는 변수를 전역변수

- 메소드 내에서만 접근 할 수 있는 변수를 지역변수

클래스 아래에서 선언된 변수는 클래스 전역에 영향을 미치지만, 

메소드 내에서 선언된 변수는 클래스 아래에서 선언된 변수보다 우선순위가 높다고 할 수 있습니다.

 

그렇다면 다음 예시의 실행결과를 예상해보자

public class Main {

      static int i = 5;
      
        static void a() {
            int i = 10;
            b();
        }
    
        static void b() {
            System.out.println(i);
        }
    
        public static void main(String[] args) {
            a();
        }
}

우선 메소드 b에는 변수 i의 값이 없으며, 클래스 변수 i가 존재하며, 

또한, 현재 메소드 a에서 메소드 b를 호출하는 상황에서 메소드 a에는 지역변수 i가 존재합니다.

아래 결과에서 클래스 변수를 사용하는 것을 확인할 수 있습니다.

사용되는 시점에서의 유효범위(메소드 a의 i)를 사용하는 것이 아니라

정의된 시점에서의 유효범위(i = 5)를 사용하는 것이다.

 

그렇다면 메소드 a의 i 를 사용하게는 못할까?

단순히 파라미터를 전달하면 될 문제이다.

이미 말했듯이 지역변수를 더 우선시하기 때문이다.

public class Main {

      static int i = 5;
      
        static void a() {
            int i = 10;
            b( i );
        }
    
        static void b( int i ) {
            System.out.println( i );
        }
    
        public static void main(String[] args) {
            a();
        }
}

 

인스턴스도 클래스와 별 차이가 없다.

class Test {
    int value = 10;

    void func() {
        int value = 20;
        System.out.println(value);
    }
}

public class Main {

    public static void main(String[] args) {
        Test t = new Test();
        t.func();
    }
}

메소드 안에서 선언된 변수 v가 지역 변수가 되면서 

인스턴스 전역에서 유효한 인스턴스 변수 v의 값보다 우선순위가 높아지면서 20 출력

 

클래스 변수 value(= 10)에 접근하려면 어떻게 해야 할까? 

this 키워드 이용 (this는 인스턴스 자신 의미)

class Test {
    int value = 10;

    void func() {
        int value = 20;
        System.out.println( this.value );
    }
}

public class Main {
    public static void main(String[] args) {

        Test t = new Test();
        t.func();
    }
}

 

유효범위란 변수를 전역변수, 지역변수 나눠서 좀 더 코드 관리를 편하게 해줍니다.

절차지향 프로그래밍에서는 모든 메소드에서 접근이 가능한 전역 변수의 사용을 권장하지는 않습니다.

물론 경우에 따라서는 전역변수를 사용함으로 좀 더 효율적일 수 있습니다.

그렇기에 연관된 변수와 메소드를 그룹핑 할 수 있도록 함으로서 

좀 더 마음놓고 객체 안에서 전역변수를 사용할 수 있도록 해야 합니다.

(단일 객체가 너무 비대해지지 않도록 적절하게 규모를 쪼개는 것이 중요)

 

 

 

 

반응형

댓글