본문 바로가기

Java/기본 이론

[JAVA] Chapter 05. 변수 - 데이터 타입과 형변환

 

1. 변수의 기본 타입 (8종류)

변수는 데이터를 담는 상자로, 자바에서는 이 상자의 크기를 지정해줘야 한다.

개발자가 담으려는 데이터의 종류에 따라 적절한 데이터 타입을 선언해야하며, 일치하지 않을 경우 데이터가 정상적으로 할당되지 않는다.

변수의 기본 타입은 총 8가지가 있으며, 나머지의 변수는 모두 '참조형 타입'의 변수이다. 

 

1) byte (정수형)

데이터의 할당크기는 1byte이며 -128~127 까지 데이터를 할당할 수 있다.

 

2) short (정수형)

데이터의 할당크기는 2byte이며 -32768~32767 까지 데이터를 할당할 수 있다.

 

3) int (정수형) : 기본값

데이터의 할당크기는 4byte이며 -2147483648~2147483647까지 데이터를 할당할 수 있다.

 

4) long (정수형)

데이터의 할당크기는 8byte이며 -922372036854775808~9223372036854775807 까지 데이터를 할당할 수 있다.

 

5) float (실수형)

데이터의 할당크기는 4byte이며 32bit 부동 소수점(데이터 할당에서 bit 사용을 유동적으로 사용하는 특성)의 데이터를 할당할 수 있다.

실수 변수 선언은 double 이 기본 값이다 때문에 float에 데이터를 저장한다면 끝에 f 혹은 (float)를 사용하여야 한다. 

 

유리수를 2로 나누어 2진수로 표현하는 방법은 결국 분수인 유리수를 나누는 것이기 때문에 2를 곱하여 계산할 수 있다.  

예) 0.625 > 1.250 > 0.5 > 1.0 = 0.101 (2) 

 

6) double (실수형): 실수형 기본값

데이터의 할당크기는 8byte이며 64bit 부동 소수점의 데이터를 할당할 수 있다. 

 

7) char (문자형)

데이터의 할당크기는 2byte이며 문자 1개의 데이터를 할당할 수 있다.

16bit 유니코드 문자를 기준으로 한다. 직접 글자 할당도 가능하지만 유니코드 넘버도 할당된다.

 

8) boolean (논리형)

데이터의 할당크기는 1byte이며 true 혹은 false 데이터를 할당한다.

참 혹은 거짓을 판단하는 데이터 변수이므로 논리형이라고 한다. 

 

2. 참조형 타입 (reference type, 사용자 정의 타입)

참조형 타입은 변수에 객체의 주소를 할당하는 방식으로, 기본형을 제외한 나머지 타입을 말한다.

개발자가 별도로 지정한 클래스 혹은 배열이 없다면 String 변수가 이에 해당한다. 

 

쉽게말해, 참조형 타입은 기본형 타입을 제외한 사용자가 필요에 의해 변수를 지정하는 모든 것을 지칭한다.

참조형 변수는 별도의 공간에 저장한 데이터를 참조형으로 할당된 코드를 통해 불러오는 방식이다. 

 

 

참조형은 스택 메모리(Stack Memory)에 저장되며 데이터에 액세스할 수 있는 위치(주소)를 저장하는 형태이다.

실제 데이터는 힙 메모리(Heap Memory)에 할당된 상태이다. (이는 Chapter 07. 데이터 영역을 확인하자)

 

스택 메모리는 정적 메모리이며 기본형 변수와 참조형 변수의 메모리 주소가 저장된다.

힙 메모리는 동적 데이터 영역으로 데이터의 정보가 뚜렷하게 정해지지 않은 상태를 말한다.

동적 데이터이기 때문에 새로운 방을 만들어준다는 개념으로 접근해야 하며, 때문에 참조형 타입은 new를 통해 방을 만들어 데이터 값을 할당해줄 필요가 있다.

 

다만 String의 경우 특수한 참조형 변수로 new가 없이 사용할 수 있다.

String으로 데이터를 선언하면 힙 메모리에 할당되고, 같은 문자라면 만약 다른 이름으로 변수를 선언해도 동일한 힙 메모리의 데이터를 참조한다. 

 

 

또한, new를 통해 선언이 가능하지만, new로 선언한 데이터는 기존 String이 할당하는 동적 메모리의 영역을 공유하지 않게 된다.

때문에 위와 같이 str2와 str1은 같은 값이 아니다.

 

3. 리터럴: 변수나 상수에 저장하고자 하는 값, 그 자체

리터럴은 프로그램 코드에서 사용되는 고정된 값(변경 불가능한 값)을 말한다.

변수에서 별도의 계산이나 처리없이 직접 사용되는 값을 리터럴이라고 한다.

 

아래의 예시를 통해 리터럴을 이해하자. 

public static void main(String[] args) {  


    boolean a = true;  
    
    byte b = 10;  
    
    short c = 20;  
    
    int d = 30;  long e = 40L;  
    
    float f = 12.5f;  
    
    double g = 34.56;  
    
    char h = 'k';  
    
    String i = "hello java";  
    
    System.out.println("boolean : " + a); 
    System.out.println("byte : " + b); 
    System.out.println("short : " + c); 
    System.out.println("int : " + d); 
    System.out.println("long : " + e); 
    System.out.println("float : " + f); 
    System.out.println("double : " + g); 
    System.out.println("char : " + h); 
    System.out.println("String : " + i); 
   
} 

위와 같이 별도의 계산 없이 할당된 모든 데이터는 리터럴이다. 

 

 

위에서 확인이 가능하듯이 long과 float의 경우, 숫자 뒤에 l과 f를 붙여 데이터의 타입을 명시해준다.

이는 기본적으로 정수와 실수의 deafault 값이 상이하기 때문인데, 실수의 경우 double이 기본 값이고, 정수의 경우 int가 기본값이다. 

기본값의 차이로 인해, long과 float는 변수 선언시에 숫자 뒤에 문자를 붙여 변수의 타입을 정확히 규정하고 표시하는 것이다.

 

결과적으로 리터럴은 특정한 계산 없이 성립된 변수의 데이터이며, 다른 변수나 연산의 기초가 된다. 

 

4. 형변환 (형변환은 기본적으로 기본 변수 사이에 적용된다.)

4.1. 자동 형변환 (Widening Casting)

형변환은 프로그램에서 타입이 다른 피연사자들을 연산할 때 하나의 타입으로 통일한 뒤 계산하는 것을 말한다.

데이터를 표현할 수 있는 작은 타입에서 큰 타입으로 변환된다.

데이터 처리를 위해 변수가 일시적으로 변하는 것을 자동 형변환이라고 한다.

 

byte → short (char) → int → long → float → double 

쉽게 말하자면, 실수인 3.5와 정수인 22를 더한다고 가정하자.

해당 결과 값은 25.5로 실수이다.

만약 정수로 해당 데이터를 담는다면 25.5에서 0.5가 누락되고 25만 데이터에 할당될 것이다.

때문에 데이터의 손실을 방지하고 정확한 연산을 위해서는 연산하는 두개의 데이터가 동일한 형태여야 한다는 것이다. 

 

4.2. 강제 형변환 (Narrowing Casting)

데이터를 처리할 때, 큰 수의 값을 작은 값으로 ‘수동’으로 할당하여 계산하는 과정을 강제 형변환이라고 한다.

큰 타입에서 작은 타입으로 변환할 때 사용하며, 대입 받는 변수의 혀에 맞춰 캐스팅된다.

캐스팅 연산자를 사용하며, 데이터 손실이 발생할 가능성이 있다.

public static void main(String[] args) {      
    
  double myDouble = 9.78;      

  int myInt = (int) myDouble; // Manual casting: double to int      

  System.out.println(myDouble);   // Outputs 9.78     
  System.out.println(myInt);      // Outputs 9
}
public static void main(String[] args) {  

  char aVar='A';  

  System.out.println("aVar :"+aVar); // Outputs A  

  System.out.println("aVar :"+(int)aVar); // Outputs 65 (아스키코드표 참고

}

 

위의 코드에서 확인할 수 있듯이, char 타입의 변수를 int로 형변환 할수도 있다.

이는 컴퓨터가 문자를 이해하는 방법이 각 문자별로 값을 할당하여 표현하는 방식이기 때문이다.

컴퓨터에 저장된 문자의 기본값은 아스키 코드 혹은 유니코드를 참고하면 알 수 있다.

 

 즉, char = 66; 으로도 데이터를 할당하고 표현할 수 있다는 것이다. 

 

5. 상수 할당: final 

숫자 변수 선언 시에 final을 변수 선언문 앞에 배치하면 해당 값은 고정된 ‘상수’ 값으로 할당된다.

해당 항목을 추후 변경하려한다면 error가 발생한다.

변수 자체는 변하는 수이지만 ‘final’에 의해 고정된 값으로 할당되는 것이다.

 

변하지 말아야할 데이터를 선언할 때 사용한다. 

int a = 5; 
a = 10; 
// (o) 

final int a = 5; 
a = 10; 
// (x)