이세개발
article thumbnail
Published 2023. 4. 16. 22:01
이것이java다 2.2 데이터 타입 legacy

모든 변수에는 타입(type : 형 形) 이 있으며, 타입에 따라 저장할 수 있는 값의 종류와 범위가 달라진다.

변수를 선언할 때 주어진 타입은 변수를 사용하는 도중에 변경할 수 없다. 따라서 변수를 선언할 때 어떤 타입을 사용할지 충분히 고려해야 한다.

 

 

 

1. 기본 ( 원시 : primitive ) 타입

 

기본(원시) 타입이란 정수, 실수 , 문자, 논리 리터럴을 직접 저장하는 타입을 말한다. 정수 타입에는 byte, char, short, int, long 이 있고, 실수타입에는 float, double 이 있다. 그리고 논리 타입에는 boolen이 있다. 다음은 각 기본 타입의 메모리 크기와 저장되는 값의 범위를 보여준다.

 

1byte = 8bit = 00000000

 

 

메모리에는 0과 1을 저장하는 최소 기억 단위인 bit(비트) 가 있다. 그리고 8개의 비트를 묶어서 byte(바이트) 라고 한다. 기본 타입은 정해진 메모리 사용 크기( 바이트 크기) 로 값을 저장하는데 바이트 크기가 클수록 표현하는 값의 범위가 크다. 각 타입에 저장되는 값의 범위를 정확히 외울 필요는 없지만, 메모리 사용 크기 정도는 알고 있는 것이 좋다. 정수 타입일 경우 -2^(n-1)~2^(n-1)-1 의 값을 저장할 수 있는데, 여기서 n 이 메모리 사용 크기(bit 수)이다. 예를들어 int 타입의 경우 4byte(32bit) 이므로 -2^31 ~ 2^31-1의 값의 범위를 갖는다. 실수 타입일 경우 가수와 지수 부분에 사용되는 bit 크기에 따라서 값의 범위가 결정된다. 이것에 대한 상세한 설명은 실수 타입을 설명할 때 하기로 하겠다.

 

 

 

 

 

2. 정수 타입

 

정수타입에는 모두 다섯개의 타입이 있으면 저장할수 있는 값의 범위가 서로 다르다.

자바는 기본적으로 정수 연산을 int 타입으로 수행한다. 그렇기 때문에 저장하려는 값이 정수 리터럴이면 특별한 이유가 없는 한 int 타입 변수에 저장하는 것이 좋다. byte와 short이 int 보다는 메모리 사용 크기가 작아서 메모리를 절약할 수는 있지만, 값의 범위가 작은 편이라서 연산시에 범위를 초과하면 잘못된 결과를 얻기 쉽다.

 

1) byte 타입

byte 타입은 색상 정보 및 파일 또는 이미지 등의 이진(바이너리) 데이터를 처리할 때 주로 사용된다. byte 타입은 정수 타입중에서 가장 작은 범위의 수를 저장하는데, 표현할 수 있는 값의 범위는 -128~127(-2^7~2^7-1) 이다. 양수가 2^7-1 인 이유는 0이 포함되기 때문이다.

만약 -128~127을 초과하는 값이 byte 타입 변수에 저장될 경우 컴파일에러 ("Type mismatch : cannot convert from int to byte) 가 발생한다. byte타입이 왜 -128~127 까지 정수값을 저장하는지 알아보면, byte 타입은 1byte, 즉 8bit 크기를 가지므로 다음과 같이 0과 1이 8 개로 구성된 이진수로 표현이 가능하다.

 

[이진수]                  [십진수]

최상위 bit                                                                                          

                                                                                                             127

 

 

0

                                                                                                             126

 

 

0 0 0 0 0 0 1

                                                                                                             1

 

 

0 0 0 0 0 0 0

                                                                                                             0

 

 

1

                                                                                                             -1

 

 

1 0

                                                                                                             -2

 

1 0 0 0 0 0 0 1

                                                                                                             -127

 

 

1 0 0 0 0 0 0 0

                                                                                                             128

 

 

 

최상위 비트는 정수값의 부호를 결정한다. 최상위 비트가 0 이면 양의 정수, 1 이면 음의 정수를 뜻한다. 실제 정수값은 나머지 7 개의 bit 로 결정된다. 최상위 비트가 1인 음수의 경우에는 나머지 7개의 bit을 모두 1의 보수(0)로 바꾸고 1을 더한값에 -를 붙여주면 10진수가 된다.

 

byte타입보다 크기가 큰 short, int, long 타입도 전체 바이트 수만 다를 뿐 동일한 원리로 정수값을 표현한다.

 

 

--------------------------[ByteExample.java] byte 타입 변수-----------------------------

public class ByteExample {

public static void main(String[] args) {

byte var1 = -128;

byte var2 = -30;

byte var3 = 0;

byte var4 = 30;

byte var5 = 127;

//byte var6 = 128;       //컴파일  에러

 

System.out.printIn(var1)

System.out.printIn(var2)

System.out.printIn(var3)

System.out.printIn(var4)

System.out.printIn(var5)

//System.out.printIn(var6)//

 

}

 

}

------------------------------------------------------------------------------------------------

Console

-128

-30

0

30

127

-----------------------------------------------------------------------------------------------

코드에서 정상적으로 변수에 올바른 값을 저장하더라도 프로그램이 실행하는 도중에 변수의 값은 변경된다. 만약 실행중에 저장할 수 있는 값의 범위를 초과하면 최소값부터 다시 반복 저장되는데 byte일 경우 -128 (최소값) 부터 시작해서 127(최대값) 을 넘으면 다시 -128 부터 시작하게 된다. 또 다른 정수 타입인 short, int, long 역시 저장할 수 있는 값의 범위를 넘어서면 이와 같은 방식으로 처리된다. 이와 같이 저장할 수 있는 값의 범위를 초과해서 값이 저장될 경우 엉터리 값이 변수에 저장되는데 이러한 값을 쓰레기값 이라고 한다. 개발자는 쓰레기값이 생기지 않도록 주의해야 한다.

다음 예제는 byte 변수와 int 변수를 각각 125로 초기화하고 5회에 걸쳐 1씩 더하기 한 다음 출력한 결과를 보여준다.

-------------------------[ GarbageValueExample.java] byte 타입 변수 ---------------------------------------

package sec02.exam01_byte;

public class GarbageValueExample {

public static void main(String[] args) {

byte var1 = 125;

int var2 = 125;

for(int i=0; i<5; i++) {

var1++;

var2++;

System.out.println("var1: " + var1 + "\t" + "var2: " + var2);

}

}

}

------------------------------------------------------------------------------------------------------------------
Console
var1: 126 var2: 126
var1: 127 var2: 127
var1: -128 var2: 128
var1: -127 var2: 129
var1: -126 var2: 130
--------------------------------------------------------------------------------------------------------------------
byte 변수는 127 넘어서는 순간 최소값인 -128 부터 다시 저장되는 것을 볼 수 있고 int 타입의 변수는 정상적으로 1 증가된 값을 계속 저장하는 것을 볼 수 있다.
 
 
2) char 타입
자바는 모든 문자를 유니코드(Unicode)로 처리한다. 유니코드는 세계 각국의 문자들을 코드값으로 매핑한 국제 표준 규약이다. 유니코드는 하나의 문자에 대해 하나의 코드값을 부여하기 떄문에 영문 'A' 및 한글 '가' 도 하나의 코드값을 가진다. 유니코드는 0~65535 범위의 2byte 크기를 가진 정수값이다. 0~127까지는 아스키(ASCII)  문자(특수기호 및 영어 알파벳) 가 할당되어 있고 44032~55203까지는 한글 11172자가 할당되어 있다. 유니코드에 대한 자세한 정보는 유니코드 홈페이지(http://www.unicode.com)에서 찾을수있다. 자바는 하나의 유니코드를 저장하기위해 2byte 크기인 char 타입을 제공한다. 유니코드는 음수가 없기 때문에 char타입에 저장할수 있는 값은 0~65535까지 2^16 개이다. char타입 변수에 작은 따옴표(')로 감싼 문자를 대입하면 해당 문자의 유니코드가 저장된다. 예를들어 'A' , 'B' , '가' ,'각' 문자를 char 변수에 저장할 경우 변수에 저장되는 유니코드 값은 다음과 같다.
 
----------------------------------------------------------------------------------------------
char var1 = 'A';               //유니코드 0x0041   => 2진수  00000000 01000001
char var2 = 'B';               //유니코드 0x0042   => 2진수  00000000 01000010
char var3 = '가';               //유니코드 0xAC00   => 2진수  10101100 01000000
char var4 = '각';               //유니코드 0xAC01   => 2진수  10101100 01000001
----------------------------------------------------------------------------------------------
 
char 변수에 작은따옴표(')로 감싼 문자가 아니라 직접 유니코드 정수값을 저장할 수도 있다. 특정 문자의 유니코드를 안다면 10진수 또는 16진수로 저장하면 되는데, 예를들어 문자 A는 10진수로 65이고, 16진수로 0x41이므로 다음과 같이 char 변수에 저장할 수 있다. 16진수로 저장할 경우에는 유니코드라는 의미에서 '\u+16진수값' 형태로 값을 저장하면 된다.
 
---------------------------------------
char c1 = 65;
char c2 = '\u0041';
--------------------------------------
 
프로그램 코드에서 char 변수에 저장된 유니코드를 알고 싶다면 char 타입 변수를 int 타입 변수에 저장하면 된다.

 

----------------------------------------

char c1 = 'A';

int uniCode = c1;

-----------------------------------------

 

 

--------------------------[ CharExample.java ] char 타입 변수 ------------------------------------------

public class CharExample {

public static void main(String[] args) {

char c1 = 'A';           //문자를 직접 저장

char c2 = 65;           //십진수로 저장

char c3 = '\u0041';    //16진수로 저장

 

char c4 = '가';          //문자를 직접 저장

char c5 = 44032;       //십진수로 저장

char c6 = '\uac00';    //16진수로 저장

 

int uniCode = c1; //유니코드 얻기

 

System.out.println(c1);

System.out.println(c2);

System.out.println(c3);

System.out.println(c4);

System.out.println(c5);

System.out.println(c6);

System.out.println(uniCode);

}

--------------------------------------------------------------------------------------------------------------------

Console

A

A

A

65

--------------------------------------------------------------------------------------------------------------------

 

char 타입의 변수에 어떤 문자를 대입하지 않고 단순히 초기화를 할 목적으로 다음과 같이 작은 따옴표(') 두개를 연달아 붙인 빈(empty) 문자를 대입하면 컴파일 에러가 발생한다. 그렇기 때문에 공백(유니코드 : 32) 하나를 포함해서 초기화 해야 한다.

 

------------------------------------------------------------------------------------------

char var1 = ''; //컴파일 에러  =>    char var1 = ' ';

 

//하지만 String 변수는 큰 따옴표 두개를 연달아붙인 빈 문자를 대입해도 괜찮다.

 

String var1 = "";

------------------------------------------------------------------------------------------

 

3) short 타입

short 타입은 2byte (16bit) 로 표현되는 정수값을 저장할 수 있는 데이터 타입이다. 저장할 수 있는 값의 범위는 -32,768~32,767 ( -2^15 ~ 2^15-1 ) 이다. C 언어와의 호환을 위해 사용되면 비교적 자바에서는 잘 사용되지 않는 타입이다. 왜냐하면 short 의 범위보다 넓은 int 타입이 있기 때문이다.

 

4)int 타입

int 타입은 4byte (32bit) 로 표현되는 정수값을 저장할 수 있는 데이터 타입이다. 저장할 수 있는 값의 범위는 -2,147,483,648~ 2,147,483,647 (-2^31 ~ 2^31-1) 이다. int 타입은 자바에서 정수 연산을 하기 위한 기본 타입이다. 쉽게 설명하면 byte 타입 또는 short 타입의 변수를 +연산하면 int 타입으로 변환된 후 연산되고 연산의 결과 역시 int 타입이 된다. 이것은 자바에서 정수연산을 4 byte로 처리하기 떄문이다. 따라서 byte 타입이나 short 타입으로 변수를 선언한 것과 int 타입으로 변수를 선언한 것의 성능 차이는 거의 없다. 자세한 내용은 2.3 자동타입변환에서 알아보고 여기서는 메모리가 크게 부족하지 않다면 정수를 저장할 때는 일반적으로  int 타입을 사용한다는 것만 알아두자. 정수값을 직접 코드에서 입력할 경우 8진수 10진수 16진수 10진수 10을 각각 8 진수와 16진수로 표현해 변수에 저장한다.

----------------------------------------------------

int number =10;

int octNumber = 012;

int hexNumber = 0xA;

--------------------------------------------

변수에 어떤 진수로 입력을 하더라도 동일한 값이 2진수로 변환되어 저장된다. 10이 int 타입 변수에 저장되면 메모리에 생성되는 변수는 다음과 같다. int 가 4 byte 크기를 가지기 떄문에 4byte의 공간을 차지하면서 총 32bit로 10을 표현한다.

 

변수

00000000  00000000   00000000   00001010

1byte        1byte        1byte         1byte

 

10은 1byte로 충분히 표현 가능하기 때문에 상위 3byte의 값은 모두 0이 된다.

 

----------------------[ IntExample.java ] int 타입 변수 ----------------------------------------

public class IntExample {

public static void main(String[] args) {

int var1 = 10; //10진수로 저장

int var2 = 012; //8진수로 저장

int var3 = 0xA; //16진수로 저장

 

System.out.println(var1);

System.out.println(var2);

System.out.println(var3);

}

}

-----------------------------------------------------------------------------------------------------

Console

10

10

10

-----------------------------------------------------------------------------------------------------
 

 

 

5) long 타입

long 타입은 8byte (64bit)로 표현되는 정수값을 저장할 수 있는 데이터 타입이다. 저장할 수 있는 값의 범위는 -9,223,372,036,854,775,808

~ 9,223,372,036,854,775,807 ( -2^63~2^63-1) 이다. 수치가 큰 데이터를 다루는 프로그램에서는 long 타입이 필수적으로 사용된다. 대표적인 예가 은행 및 우주와 관련된 프로그램들이다. long 타입의 변수를 초기화 할 떄에는 정수값 뒤에 소문자 'ㅣ'이나 대문자 'L'을 붙일 수 있다. 이것은 4byte 정수 데이터가 아니라 8byte 정수 데이터임을 컴파일러에게 알려주기 위한 목적이다. int 타입의 저장 범위를 넘어서는 큰 정수는 반드시 소문자 'ㅣ'이나 대문자'L' 을 붙여야 한다. 그렇지 않으면 컴파일 에러가 난다. 일반적으로 소문자'l'은 숫자 '1'과 비슷해 혼돈하기 쉬우므로 대문자 'L'을 사용한다.

 

--------------[ LongExample.java ] long 타입 변수 -------------------------

public class LongExample {

public static void main(String[] args) {

long var1 = 10;

long var2 = 20L;

//long var3 = 1000000000000;     //컴파일 에러

long var4 = 1000000000000L;

 

System.out.println(var1);

System.out.println(var2);

System.out.println(var4);

}

-----------------------------------------------------------------------------

Console

10

20

1000000000000

-----------------------------------------------------------------------------

5라인에서 컴파일에러('The literal 10000000000 of type int is out of range) 가 나는이유는 int 타입의 저장 범위를 넘어서는 정수리터럴에 L 을 붙이지 않았기 때문이다.

 

 

3. 실수 타입

 

실수타입은 소수점이 있는 실수 데이터를 저장할 수 있는 타입으로, 메모리 사용 크기에 따라 float 과 double 이 있다.

float과 double의 메모리 사용 크기는 각각 int 와 long 의 크기와 같지만, 정수 타입과는 다른 저장 방식 때문에 정수 타입보다 훨씬 큰 범위의 값을 저장할 수 있다. 실수는 정수와 달리 부동소수점(floating-point) 방식으로 저장된다. 부동 소수점 방식은 실수를 다음과 같은 형태로 표현한다.

부호,가수(mantissa),지수(exponent)

가수 M 은  0 ≤ m < 1 범위의 실수여야 한다. 예를들어 실수 1.2345는 부동 소수점 방식으로 표현하면

0.12345 x 10^1 이며 가수는 0.12345 이고 지수는 1이 된다. float 타입과 double타입은 가수와 지수를 저장하기 위해 전체 bit을 나누어 사용한다. 다음은 float과 double 타입이 전체 bit을 어떻게 사용하는지 정리한것이다.

 

float : 부호 1bit + 지수 8bit + 가수 23bit = 32bit = 4byte

 지수 (8bit)   가수 (23bit)

 

double : 부호 1bit + 지수 11bit + 가수 52bit = 64bit = 8byte

 지수 (11bit)   가수 (52bit)

 

위의 표에서 가수를 표현하는데 있어서 float에 비해 double이 약 두배의 자릿수가 배정되어 있다. 따라서 float 보다 double이 더 정밀한 값을 저장할 수 있기 때문에 높은 정밀도를 요구하는 계산에서는 double을 사용해야 한다. 자바는 실수 리터럴의 기본타입을 double로 간주한다. 이말은 실수 리터럴을 float 타입 변수에 그냥 저장할 수 없다는 뜻이다. 실수 리터럴을 float 타입 변수에 저장하려면 리터럴 뒤에 소문자 'f' 나 대문자 'F'를 붙여야 한다.

--------------------------------------------------------------

double var1 = 3.14;

float var2 = 3.14;              //컴파일 에러 (Type mismatch : cannot convert from double to float)

float var3 = 3.14F;

--------------------------------------------------------------

 

만약 정수 리터럴에 10의 지수를 나타내는 e 또는 E 를 포함하고 있으면 정수타입 변수에 저장할 수 없고 실수타입 변수에 저장해야 한다.

다음은 정수값 300000을 저장하는 방법을 보여준다.

-----------------------------------------------------------------

int var6 = 3000000;       //3000000

double var7 = 3e6;       //3000000

float var8 = 3e6F;         //3000000

double var9 = 2e-3;       //3000000

-------------------------------------------------------------

 

----------------------------[ FloatDoubleExample.java ] -----------------------------------------------------------

public class FloatDoubleExample {

public static void main(String[] args) {

//실수값 저장

double var1 = 3.14;

//float var2 = 3.14; //컴파일 에러(Type mismatch)

float var3 = 3.14F;

 

//정밀도 테스트

double var4 = 0.1234567890123456789;

float var5 = 0.1234567890123456789F;

 

System.out.println("var1: " + var1);

System.out.println("var2: " + var3);

System.out.println("var4: " + var4);

System.out.println("var5: " + var5);

 

//e 사용하기

int var6 = 3000000;

double var7 = 3e6;

float var8 = 3e6F;

double var9 = 2e-3;

System.out.println("var6: " + var6);

System.out.println("var7: " + var7);

System.out.println("var8: " + var8);

System.out.println("var9: " + var9);

}

--------------------------------------------------------------------------------------------------------------------------
Console

var1: 3.14

var2: 3.14

var4: 0.12345678901234568

var5: 0.12345679

var6: 3000000

var7: 3000000.0

var8: 3000000.0

var9: 0.002

--------------------------------------------------------------------------------------------------------------------------------

float과 double의 정밀도 테스트를 하기위해 var4 와 var5 에 같은 값을 넣고 출력해보니 , double타입인 var4가 float 타입인 var5 보다 두배 이상 정밀하게 값이 저장되어 있는것을 볼 수 있다. 이것은 double 타입의 가수bit 수가 float타입의 가수 bit수 보다 약 두배 정도 크기 떄문이다.

 

 

 

4. 논리 타입

boolean 타입은 1byte(8bit) 로 표현되는 논리값 (true,false)을 저장할 수 있는 데이터 타입이다. boolean 타입은 두 가지 상태값을 저장할 필요성이 있을 경우에 사용되며, 상태값에 따라 조건문과 제어문의 실행 흐름을 변경하는데 주로 이용된다. 예를들어 다음 코드를 보면 stop 변수에 true가 저장되어 있기 때문에 if 블록을 실행해서 "중지합니다" 가 출력된다. 만약 stop 변수에 false가 저장되어 있다면 else 블록이 실행되어 " 시작합니다." 를 출력한다. stop 변수에 값을 변경해보면서 출력 내용을 확인해보길 바란다.

 

--------------------------[ BooleanExample.java ] boolean 타입 -------------------------------

public class BooleanExample {

public static void main(String[] args) {

boolean stop = true;           //boolean stop = false;  

if(stop) {

System.out.println("중지합니다.");

} else {

System.out.println("시작합니다.");

}

}

---------------------------------------------------------------------------------------------------

Console

중지합니다.

 

(false) 일경우 

시작합니다.

---------------------------------------------------------------------------------------------------

'legacy' 카테고리의 다른 글

이것이java다 1. 확인문제풀이  (0) 2023.04.16
이것이java다 2.1 변수  (0) 2023.04.16
이것이java다 2.3 타입 변환  (0) 2023.04.16
이것이java다 2. 확인문제 풀이  (0) 2023.04.16
이것이java다 3.1 연산자와 연산식  (0) 2023.04.16
profile

이세개발

@print(name)

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!