[자바] 기초문법정리(스코프)(230103)

brand_mins·2024년 1월 3일

Java

목록 보기
32/47

1. 스코프, 형변환

1) 지역변수와 스코프

  • 지역변수: 특정 지역에서 사용할 수 있는 변수
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 = " + m);
    } // m 생존 종료
}
  • int m
- main() 메서드의 코드 블록 안에서 선언
- main 메서드가 종료될때까지 생존.
  • int x
- if() 블록 안에서 선언되었고 if문이 종료될때까지 생존
- if문 이후에 접근하게 되면 cannot find symbol 이라는 변수 이름을 찾을 수 없다는 컴파일 오류 발생

(1) 예시: for문을 활용한 스코프

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 생존 종료
    }
}

2) 스코프 존재 이유

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, temp가 존재함.
  • temp는 if문에 위치해야 메모리 관리에 적절함.
  • 하지만, 현재 코드를 보면 temp는 전역변수 main 메서드 안에 위치되어 있어 비효율적인 메모리 사용
  • 그리고 코드 복잡성이 증가된다. if문이 종료되면 이후에 코딩할때 m과 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);
    }
}
  • if문이 아니더라도 for문과 while문에서도 스코프를 적용할 수 있다.
package loop;

public class While2_3 {

    public static void main(String[] args) {
        int sum = 0;
        int i = 1;
        int endNum = 10;

        while (i <= endNum) {
            sum = sum + i;
            System.out.println("i=" + i + ", sum=" + sum);
            i++;
        }
    }
}
  • while문은 i의 스코프가 main메서드 전체가 된다.
package loop;

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);
        }
    }
}
  • for문은 i의 스코프가 for문 안에 위치되어있다.
  • 따라서, 변수 i와 같이 for문 안에서만 사용할 수 있는 카운터변수가 존재한다면 for문을 사용해서 스코프 범위를 줄인다.

스코프 정리

  • 변수는 범위를 한정해서 사용하자.
  • 좋은 프로그램은 적절한 제약이 있는 프로그램이다.

2. 형변환

1) 자동 형변환

(1) 형변환

  • 작은 범위에서 큰 범위로 값을 변환함.
int < long < double
- int보다는 long . long보다는 double
  • 큰 범위에서 작은 범위는 소수점을 버리거나 오버플로우 발생
// intValue = 10;
doubleValue = intValue;
doubleValue = (double) intValue; // 형 맞추기
doubleValue = (double) 10; // 값 읽기
doubleValue = 10.0; // 형변환
package casting;

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("doubleValue = " + doubleValue);

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

2) 명시적 형변환

  • 큰 범위에서 작은 범위로 변환
package casting;

public class Casting2 {

    public static void main(String[] args) {
        double doubleValue = 1.5;
        int intValue = 0;

        //intValue = doubleValue; // 컴파일 오류 발생(타입)
        intValue = (int) doubleValue; // int형으로 형변환
        System.out.println(intValue);
    }
}

(1) 형변환(캐스팅)

  • 개발자가 직접 감수하고도 값을 대입하고자 할때 타입을 강제로 변경

1) 형변환 과정

// doubleValue = 2.5;
intValue = (int) doubleValue;
intValue = (int) 2.5; // doubleValue에 있는 값을 읽기
intValue = 2; // intValue에 int형인 숫자2 대입

(2) 형변환과 오버플로우

  • 형변환할때 만약 작은 숫자가 표현할 수 있는 범위를 넘어선다면 오버플로우 발생.
package casting;

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);

        intValue = (int) maxIntOver; // 형변환. 위의 maxIntOver 숫자 크기를 늘리면 작은 범위의 값부터 다시 시작. (오버플로우)
        System.out.println("maxIntOver casting = " + intValue);
    }
}
  • 과정 설명
maxIntOver = 214783648L; // int 최고값 + 1
intValue = (int) maxIntOver;
intValue = (int) 214783648L; // 형변환시도
intValue = -214783648;
  • 기존 범위를 벗어나면 오버플로우가 발생하여 처음 값부터 다시 시작.
  • 이 경우 int형에서 long형으로 다시 변환해주면 문제 해결됨.

3) 계산과 형변환

package casting;

public class Casting4 {

    public static void main(String[] args) {
        int div1 = 3 / 2;
        System.out.println("div1 = " + div1);
        
        double div2 = 3 / 2;
        System.out.println("div2 = " + div2);
        
        double div3 = 3.0 / 2;
        System.out.println("div3 = " + div3);
        
        double div4 = (double) 3 / 2;
        System.out.println("div4 = " + div4);
        
        int a = 3;
        int b = 2;
        double result = (double) a / b;
        System.out.println("result = " + result);
    }
}
  • 자바에서의 계산은 2가지 기억
  1. 같은 타입끼리의 연산은 같은 타입의 결과만
  2. 서로 다른 타입의 계산은 큰 범위로 자동 형변환
profile
IT 개발자가 되기 위한 기록

0개의 댓글