[이것이자바다] chapter 2. 변수와 타입

chapter2

변수와 타입

변수

리터럴이란 소스 코드 내에서 직접 입력된 값을 말한다.(상수x, 변할수 있다.)

논리 리터럴
= true, false
=> 논리 리터럴을 저장할 수 있는 타입은 boolean 하나뿐이다.

메소드 블록 내에서 선언된 변수: 로컬 변수(local variable)
=> 로컬 변수는 실행이 끝나면 메모리에서 자동으로 없어진다.

데이터 타입

primitive type 값의 종류 메모리 사용 크기 저장되는 값의 범위
byte 정수 1byte = 8bit -128~127
char 정수 2byte = 16bit 0 ~ 2^16-1
short 정수 2byte = 16bit -2^15 ~ 2^15-1
int 정수 4byte = 32bit -2^31 ~ 2^31-1
long 정수 8byte = 64bit -2^63 ~ 2^63-1
float 실수 4byte = 32bit 오차가 있는 값의 범위
double 실수 8byte = 64bit 오차가 있는 값의 범위
boolean 논리 1byte = 8bit true, false

타입 변환

  1. 자동 타입 변환(Promotion)

=> 자동 타입 변환(Promotion)은 프로그램 실행 도중에 자동적으로 타입 변환이 일어나는 것을 말한다.
자동 타입 변환은 작은 크기를 가지는 타입이 큰 크기를 가지는 타입에 저장될 때 발생한다.

크기별 type

 byte(1) < short(2) < int(4) < long(8) < float(4) < double(8)

=> float은 long보다 더 넓은 범위의 수를 표현할 수 있기 때문에 long보다 큰 크기 타입이다 . 즉 정수 타입 < 실수 타입

byte byteValue = 10;
int intValue = byteValue; // 자동 타입 변환이 일어난다.

int value = 20;
double doubleValue = value; // 20.0으로 자동 타입 변환이 일어난다.

아래의 표처럼 byteValue는 int형 intValue로 자동 타입 변환이 되어 크기가 1byte에서 4yte으로 확장되고,(byte -> int)
그 값이 intValue에 assign 된다. (원래 byteValue는 byte타입을 유지 한다.)

byte 타입
00001010
int 타입      
00000000 00000000 00000000 00001010

자동 타입 변환의 단 하나의 예외:
=> char는 byte 보다 크므로 byte가 char로 자동 타입 변환되어야 하는게 정상이다.
하지만 byte는 음수도 범위에 포함되지만 char의 범위 중 음수가 없으므로 컴파일 오류가 발생한다
이럴땐 강제 타입 변환(castiong)을 통해 해결한다.

byte byteValue = 4;
//char charValue = byteValue; // 컴파일 에러 
char charValue = (char)byteValue; // 해결

연산식에서의 자동 타입 변환.

int intValue = 10;
double doubleValue = 5.5;
double result = intValue + doubleValue;  // result = 15.5 
               //10 -> 10.0으로 자동 형변환

==> 연산은 기본적으로 같은 타입의 피연산자(operand)간에만 수행되기 때문에 서로 다른 타입의 피연산자가 있을 경우,
두 피연산자 중 크기가 큰 타입으로 자동 형 변환된 후 연산을 수행한다.
위의 경우도 intValue가 연산시 double형으로 자동형변환되어 10->10.0 이 되었고 최종적으로 result 의 값은 15.5가 되었다.

  1. 강제 타입 변환(Casting) 큰 크기의 타입은 작은 크기의 타입으로 자동 형 변환을 할 수 없다.
    이 이치는 큰 그릇에 있는 물을 작은 그릇 안에 모두 담을 수 없는 것과 같은 이치이다.
    하지만 큰 그릇을 작은 그릇 사이즈로 쪼개어서 한 조각만 작은 그릇에 넣는다면 가능하다.
    이것이 바로 강제 형 변환(Casting)이다.
public class Casting {

    public static void main(String[] args) {
        int intValue = 103029770;
        byte byteValue = (byte)intValue;  // 의미없는 강제 형 변환
        
        System.out.printf("intValue: %d \n",intValue); // 103029770
        System.out.printf("byteValue: %d \n",byteValue); // 10 => 값이 잘려 나간다. 
        
        int a = 10;
        byte b = (byte)a;  // 의미있는 강제 형 변환
        
        System.out.printf("intValue: %d \n",intValue); // 10
        System.out.printf("byteValue: %d \n",byteValue); // 10 => 값이 잘려 나가지 않는다. 
    }
}

=> 4byte의 크기를 가진 int형 변수 intValue는 103029770을 온전히 다 저장할 수 있지만,
intValue를 강제 형 변환하면 4byte 중 MSB 쪽 3byte가 날라가므로 110001001000001110000001010(2) 에서 00001010(2)만 보존된다.
따라서 byteValue에 00001010(2)만 assign 하였으므로 값은 10이 된다.

따라서 intValue의 값이 byteValue로 온전히 보존이 안된채로 assign되므로 이는 강제 형 변환을 하면 안되는 case이다.
intValue의 값이 byte의 범위에 있는 값이라면 강제 형변환이 의미가 있어지게 된다.

import java.util.Scanner;

public class CheckValueBeforeCasting {
    public static void main(String[] args) {
        int i;
        byte j;
        Scanner sc = new Scanner(System.in);
        System.out.print("i의 값을 입력하시오: ");

        i = sc.nextInt();
        if(i > Byte.MAX_VALUE || i < Byte.MIN_VALUE) {
            System.out.println("byte 타입으로 변환할 수 없습니다.");
        }
        else{
          j = (byte) i; //바이트 단위로 강제 형변환(Casting)
            System.out.printf("j= %d \n", j);
        }
    }
}