김영한 자바 입문 | 섹션 6. 스코프, 형변환

heige·2023년 12월 27일

Java

목록 보기
11/21
post-thumbnail

스코프, 형변환

필요한 내용만 정리.

스코프(Scope)

유지/보수하기 좋은 코드를 짜기 위해 꼭 알아야 한다.

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

위 코드는 좋은 코드라고 보기는 어렵다. 왜냐하면 임시 변수 tempif 내에서만 임시로 잠깐 사용하는 변수인데, main() 코드 블록에 선언되어 있다. 이렇게 되면 다음과 같은 문제가 발생한다.

  • 비효율적인 메모리 사용: tempif 코드 블록에서만 필요하지만, main() 코드 블록이 종료될 때 까지 메모리 에 유지된다. 따라서 불필요한 메모리가 낭비된다.
    만약 if 코드 블록 안에 temp 를 선언했다면 자바를 구현하 는곳에서 if 코드블록의 종료시점에 이 변수를 메모리에서 제거해서 더 효율적으로 메모리를 사용할 수 있다.
  • 코드 복잡성 증가: 좋은 코드는 군더더기 없는 단순한 코드이다. tempif 코드 블록에서만 필요하고, 여기서 만 사용하면 된다. 만약 if 코드블록 안에 temp 를 선언했다면 if 가 끝나고 나면 temp 를 전혀 생각하지 않아도된다. 머리 속에서 생각할 변수를 하나 줄일 수 있다. 그런데 지금 작성한 코드는 if 코드블록이 끝나도 main() 어디서나 temp 를 여전히 접근할 수 있다. 누군가 이 코드를 유지보수 할 때 m 은 물론이고 temp 까지
    계속 신경써야 한다.
    스코프가 불필요하게 넓은 것이다. 실무에서는 코드가 매우 복잡한 경우가 많기 때문에 주의.

형변환(Casting)

형(타입)을 바꾼다고 해서 형변환이라 한다. 영어로는 캐스팅(Casting)이라 한다.

자동 형변환

자동 형변환

  • 작은 범위에서 큰 범위로는 당연히 값을 넣을 수 있다.
    • 예) int long double
  • 큰 범위에서 작은 범위는 다음과 같은 문제가 발생할 수 있다.
    • 소수점 버림
    • 오버플로우

작은 범위에서 큰 범위로 대입은 허용한다.
int < long < double

하지만 결국 대입하는 형(타입)을 맞추어야 하기 때문에 개념적으로는 다음과 같이 동작한다.

이렇게 앞에 (double) 과 같이 적어주면 int 형이 double 형으로 변한다. 이렇게 형이 변경되는 것을 형변환이라 한다.
작은 범위 숫자 타입에서 큰 범위 숫자 타입으로의 대입은 개발자가 이렇게 직접 형변환을 하지 않아도 된다. 이런 과정 이 자동으로 일어나기 때문에 자동 형변환, 또는 묵시적 형변환이라 한다.

명시적 형변환

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

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

intValue = doubleValue //컴파일 오류 발생

명시적 형변환

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

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

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

참고로 형변환을 한다고 해서 doubleValue 자체의 타입이 변경되거나 그 안에 있는 값이 변경되는 것은 아니다.
doubleValue 에서 읽은 값을 형변환 하는 것이다. doubleValue 안에 들어있는 값은 1.5 로 그대로 유지된다.

형변환과 오버플로우

작은 숫자가 표현할 수 있는 범위 넘어서면?

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); //출력:2147483647
        
		intValue = (int) maxIntOver; //형변환
		System.out.println("maxIntOver casting=" + intValue); //출력:-2147483648 }
}

/*
maxIntValue casting=2147483647
maxIntOver  casting=-2147483648
*/
  • 정상범위
    long maxIntValue = 2147483647 를 보면 int 로 표현할 수 있는 가장 큰 숫자인 2147483647 를 입력했다. 이경우 int 로 표현할 수 있는 범위에 포함되기 때문에 다음과 같이 long ➡️int 로 형변환을 해도 아무런 문제가 없다.
  • 초과범위(오버플로우)
    • long maxIntOver = 2147483648L 를 보면 int 로 표현할 수 있는 가장 큰 숫자인 2147483647 보 다 1큰 숫자를 입력했다. 이 숫자는 리터럴은 int 범위를 넘어가기 때문에 마지막에 L 을 붙여서 long 형을 사용해야 한다. 이 경우 int 로 표현할 수 있는 범위를 넘기 때문에 다음과 같이 long ➡️int 로 형변환하면 문제가 발생한다.
    • 결과를 보면 -2147483648 이라는 전혀 다른 숫자가 보인다. int 형은 2147483648L 를 표현할 수 있는 방 법이 없다. 이렇게 기존 범위를 초과해서 표현하게 되면 전혀 다른 숫자가 표현되는데, 이런 현상을 오버플로우라 한다.
    • 오버플로우 자체가 발생하지 않도록 막아야 한다. 이 경우 단순히 대입하는 변수(intValue )의 타입을 int ➡️long 으로 변경해서 사이즈를 늘리면 오버플로우 문제가 해결된다.

계산과 형변환

package casting;
public class Casting4 {
     public static void main(String[] args) {
         int div1 = 3 / 2;
         System.out.println("div1 = " + div1); //1
         double div2 = 3 / 2;
         System.out.println("div2 = " + div2); //1.0
         double div3 = 3.0 / 2;
         System.out.println("div3 = " + div3); //1.5
         double div4 = (double) 3 / 2;
         System.out.println("div4 = " + div4); //1.5
         int a = 3;
         int b = 2;
         double result = (double) a / b;
         System.out.println("result = " + result); //1.5
} }

두 가지만 기억하기.

  1. 같은 타입끼리의 계산은 같은 타입의 결과를 낸다.
  • int + intint 를, double + doubledouble 의 결과가 나온다.
  1. 서로 다른 타입의 계산은 큰 범위로 자동 형변환이 일어난다.
  • int + longlong + long 으로 자동 형변환이 일어난다.
  • int + doubledouble + double 로 자동 형변환이 일어난다.
int div1 = 3 / 2; //int / int
int div1 = 1; //int / int이므로 int타입으로 결과가 나온다.
double div2 = 3 / 2; //int / int
double div2 = 1; //int / int이므로 int타입으로 결과가 나온다.
double div2 = (double) 1; //int -> double에 대입해야 한다. 자동 형변환 발생
double div2 = 1.0; // 1(int) -> 1.0(double)로 형변환 되었다.
double div3 = 3.0 / 2; //double / int
double div3 = 3.0 / (double) 2; //double / int이므로, double / double로 형변환이 발생한.
double div3 = 3.0 / 2.0; //double / double -> double이 된다.
double div3 = 1.5;
double div4 = (double) 3 / 2; //명시적 형변환을 사용했다. (double) int / int
double div4 = (double) 3 / (double) 2; //double / int이므로, double / double로 형변
환이 발생한다.
double div4 = 3.0 / 2.0; //double / double -> double이 된다.
double div4 = 1.5;
profile
웹 백엔드와 클라우드 정복을 위해 탄탄한 기반을 쌓아가고 있는 예비개발자입니다. 'IT You Up'은 'Eat You Up'이라는 표현에서 비롯되어, IT 지식을 끝까지 먹어치운다는 담고 있습니다.

0개의 댓글