본문 바로가기
IT/김영한의JAVA입문_inFlearn

6. 스코프, 형변화 - 지역 변수와 스코프 / 스코프 존재 이유 / 자동 형변환 / 명시적 형변환 / 계산과 형변환

by for-learn 2024. 12. 27.

6-1. 스코프1 - 지역 변수와 스코프

변수

선언한 위치에 따라 분류됨

지역변수, 멤버 변수(클래스 변수, 인스턴스 변수)

지역 변수 (=로컬 변수 Local Variable)
특정 지역에서만 사용할 수 있는 변수
이 지역은 변수가 선언된 코드 블록{ }이다. 

 

Scope1.java

package scope;

public class Scope1 {
    public static void main(String[] args) {
        int m = 10; // m 생존 시작
        if (true) {
            int x = 20; // x 생존 시작
            System.out.println("if m = " + m); // 블록 내부에서 블록 외부는 접근 가능
            System.out.println("if x = " + x);
        } // x 생존 종료
        // System.out.println("main x = " + x); // 오류, 변수 x에 접근 불가
        System.out.println("main m = " + m);
    } // m 생존 종료
}

  • int m은 main{ } 의 코드 블록 안에 선언되어 if{ } 블록 내부에서도 접근 가능하다
  • int x는 if{ } 블록 안에서 선언된다. if{ } 블록이 끝나면, x 는 제거 되기에 더는 x 에 접근할 수 없다. 

스코프 (Scope)

변수의 접근 가능한 범위

Scope2.java

package scope;

public class Scope2 {
    public static void main(String[] args) {
        int m = 10;
        for (int i = 0; i < 2; i++) { // 블록 내부, for문 내
            System.out.println("for m = " + m); // 블록 내부에서 외부는 접근 가능
            System.out.println("for i = " + i);
        } // i 생존 종료
        // System.out.println("main i = " + i); // 오류, i에 접근 불가
        System.out.println("main m = " + m);
    }
}

 

6-2. 스코프2 - 스코프 존재 이유

Scope3_1.java

package scope;

public class Scope3_1 {
    public static void main(String[] args) {
        int m = 10;
        int temp = 0;
        if (m > 0) {
            temp = m * 2;
            System.out.println("temp = " + temp);
        }
        System.out.println("m = " + m);
    }
}
  • 조건이 맞으면 변수 m의 값을 2배 증가해 출력하는 코드
  • 2배 증가한 값을 저장하기 위해 임시 변수 temp 사용
  • 좋은 코드가 아닌 이유 
    • 비효율적인 메모리 사용: 임시 변수 temp는 if 코드 블록에서만 필요. 하지만 main{ } 코드 블록에 선언되어 있어 main{ } 코드 블록이 종료될 때까지 유지되어 메모리를 낭비된다. 
    • 코드 복잡성 증가: main{ } 어디서나 temp를 여전히 접근할 수 있다. 누군가 이 코드를 유지보수 할 때 m 은 물론이고 temp 까지 계속 신경써야 한다.

Scope3_2.java (temp 변수 선언 위치 변경)

package scope;

public class Scope3_2 {
    public static void main(String[] args) {
        int m = 10;
        if (m > 0) {
            int temp = m * 2;
            System.out.println("temp = " + temp);
        }
        System.out.println("m = " + m);
    }
}

 

while문 vs for문 - 스코프 관점

더보기
public class While2_3 {
    public static void main(String[] args) {
        int sum = 0;
        int i = 1;
        int endNum = 3;

        while (i <= endNum) {
            sum = sum + 1;
            System.out.println("i=" + i + " sum=" + sum);
            i++;
        }
    }
}
public class For2 {
    public static void main(String[] args) {
        int sum = 0;
        int endNum = 3;

        for (int i = 1; i <= endNum; i++) {
            sum = sum + i;
            System.out.println("i=" + i + " sum=" + sum);
        }
    }
}
  • while문의 경우 변수 i 의 스코프가 main() 메서드 전체가 된다
  • 반면, for문은 변수 i 의 스코프가 for문 안으로 한정되어 스코프의 범위를 제한한다.
  • 메모리 사용과 유지보수 관점에서 for문을 사용하는 것이 더 좋다. 

 

6-3. 형변환1 - 자동 형변환

형변환(casting)

작은 범위에서 큰 범위로 값을 넣을 수 있다. 

ex) int -> long -> double

 

큰 범위에서 작은 범위 문제가 발생할 수 있다. 

소수점 버림, 오버플로우

작은 범위에서 큰 범위로 대입은 자바 언어에서 허용한다. => 자동 형변환

 

Casting1.java

package scope;

public class Casting1 {
    public static void main(String[] args) {
        int intValue = 10;
        long longValue;
        double doubleValue;

        longValue = intValue; // int -> long
        System.out.println("longValue = " + longValue); 

        doubleValue = intValue; // int -> double
        System.out.println("doubleValue1 = " + doubleValue); 

        doubleValue = 20L; // long -> double
        System.out.println("doubleValue2 = " + doubleValue); 
    }
}

자동 형변환 (= 묵시적 형변환) 과정

자동 형변환 과정

// intValue = 10
doubleValue = intValue
doubleValue = (double) intValue // 형 맞추기
doubleValue = (double) 10 // 변수 값 읽기
doubleValue = 10.0 // 형변환

 

6-4. 형변환2 - 명시적 형변환

큰 범위에서 작은 범위 대입은 명시적 형변환이 필요

 

Casting2.java

package scope;

public class Casting2 {
    public static void main(String[] args) {
        double doubleValue = 1.5;
        int intValue = 0;
        
        // intValue = doubleValue; // 컴파일 오류 발생
        intValue = (int) doubleValue; // 형변환
        System.out.println(intValue); // 출력:1
    }
}
  • 숫자가 손실되는 문제가 발생할 수 있어 컴파일 오류를 발생시킨다. ex) 은행 프로그램 이자 지급 코드

명시적 형변환

형변환은 다음과 같이 변경하고 싶은 데이터 타입을 (int) 와 같이 괄호를 사용해서 명시적으로 입력

intValue = (int) doubleValue; // 형변환

개발자가 직접 형변환 코드를 입력한다

 

명시적 형변환 과정

// doubleValue = 1.5
intValue = (int) doubleValue;
intValue = (int) 1.5; // doubleValue에 있는 값을 읽는다.
intValue = 1; // (int)로 형변환 한다. intValue에 int형인 숫자 1을 대입한다.

 

Casting3.java (형변환과 오버플로우)

package scope;

public class Casting3 {
    public static void main(String[] args) {
        long maxIntValue = 2147483647; // int 최고값
        long maxIntOver = 2147483648L; // int 최고값 + 1(초과)
        int intValue = 0;
        
        intValue = (int) maxIntValue; // 형변환
        System.out.println("maxIntValue casting = " + intValue); // 출력:2147483647
        
        intValue = (int) maxIntOver; // 오버플로우
        System.out.println("maxIntOver casting = " + intValue); // 출력:-2147483648
    }
}

  • 보통 오버플로우가 발생하면 마치 시계가 한바퀴 돈 것 처럼 다시 처음부터 시작한다.
  • 참고로 -2147483648 숫자는 int 의 가장 작은 숫자이다.
  • 오버플로우 발생 자체가 문제다. => 변수타입을 long으로 변경해서 예방

 

6-5. 계산과 형변환

Casting4.java 

package scope;

public class Casting4 {
    public static void main(String[] args) {
        int div1 = 3 / 2; // int/int
        System.out.println("div1 = " + div1); // 1

        double div2 = 3 / 2; // int/int
        System.out.println("div2 = " + div2); // 1.0

        double div3 = 3.0 / 2; // double/int -> double/double
        System.out.println("div3 = " + div3); // 1.5

        double div4 = (double) 3 / 2; // double/int -> double/double
        System.out.println("div4 = " + div4); // 1.5
        
        int a = 3;
        int b = 2;
        double result = (double) a / b; // a를 double로 casting
        System.out.println("result = " + result); // 1.5
    }
}

  • 같은 타입끼리의 계산같은 타입의 결과를 낸다.
    • int + intint 를, double + doubledouble 의 결과가 나온다.
  • 서로 다른 타입의 계산큰 범위로 자동 형변환이 일어난다.
    • int + longlong + long 으로 자동 형변환이 일어난다.
    • int + doubledouble + double 로 자동 형변환이 일어난다.