| 2. 변수의 타입(Type) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
모든 변수에는 타입(Type 또는 형形)이 있으며, 변수의 타입 따라 변수에 저장할 수 있는 값의 종류와 범위가 달라진다. 변수를 선언할 때 저장하고자 하는 값을 고려하여 가장 알맞은 타입을 선택하면 된다. 변수의 타입은 크게 기본형과 참조형, 2가지로 나눌 수 있는데, 기본형 변수는 실제 값(Data)을 저장하는 반면에, 참조형 변수는 어떤 값이 저장되어 있는 주소를 값으로 갖는다. 자바는 C언어와는 달리 String을 제외한 참조형 변수간의 연산을 할 수 없으므로 실제 연산에 사용되는 것은 모두 기본형 변수이다.
기본형의 개수는 모두 8개이고, 참조형은 프로그래머가 직접 만들어 추가할 수 있으므로 그 수가 정해져 있지 않다. 참조형 변수를 선언할 때는 변수의 타입으로 클래스의 이름을 사용하므로 클래스의 이름이 변수의 타입이 된다. 그러므로 새로운 클래스를 작성한다는 것은 새로운 참조형을 추가하는 셈이다. 다음은 참조변수를 선언하는 방법이다.
Date클래스 타입의 참조변수 today를 선언한 것이다. 참조형 변수는 null 또는 객체의 주소를 값으로 갖으며 참조변수의 초기화는 다음과 같이 한다.
객체를 생성하는 연산자 new의 연산결과는 생성된 객체의 주소이다. 이 주소가 대입연산자(=)에 의해서 참조변수 today에 저장되는 것이다. 이제 참조변수 today를 이용해서 생성된 객체를 사용할 수 있게 된다. [참고]기본형은 저장할 값(Data)의 종류에 따라 구분되므로 기본형 변수의 종류를 얘기할 때는 자료형(Data Type)이라는 용어를 쓰고, 모든 참조형은 종류에 관계없이 4 byte의 주소(0x0 ~ 0xffffffff 또는 null)을 저장하기 때문에, 참조형 변수들은 값(Data)이 아닌, 어떤 객체의 주소를 담을 것인가에 따른 객체의 종류에 의해서 구분되므로, 참조형 변수의 종류를 구분할 때는 자료형(Data Type)대신 타입(Type)이라는 용어를 사용한다. 타입이 자료형을 포함하는 보다 넓은 의미의 용어이므로 반드시 구분해서 사용할 필요는 없다. 2.1 기본형(Primitive Types) 기본형에는 모두 8개의 타입이 있으며, 크게 논리형, 문자형, 정수형, 실수형, 4가지로 구분된다.
[표2-2]기본형의 종류와 크기 [참고] 4개의 정수형(byte, short, int, long)중에서 int형이 기본(default) 자료형이며, 실수형(float, double)중에서는 double형이 기본 자료형이다. 논리형인 boolean은 나머지 7개의 자료형과 연산이 가능하지 않지만, char는 문자를 내부적으로 정수값 코드로 저장하고 있기 때문에 정수형과 밀접한 관계가 있다. 정수형과 실수형의 경우에는 여러 개의 변수형이 있지만, 특별히 큰 값을 다루어야 하지 않는 한 int 와 float를 주로 사용한다.
[표2-3] 8가지 기본형(Primitive Type)과 저장 가능한 값의 범위 [참고] float와 double의 음의 최대값과 최소값은 양의 최대값과 최소값에 각각 음수 부호를 붙이면 된다. 실수형은 소수점이하의 자리수, 즉 정밀도가 중요하기 때문에, 얼마나 0에 가까운 값을 표현할 수 있는지도 큰 의미를 갖는다. 각 자료형이 가질 수 있는 값의 범위를 정확히 외울 필요는 없고, 정수형(byte, short, int, long)의 경우 -2n-1~ 2n-1-1(n: bit수)이라는 정도만 기억하고 있으면 된다. 예를 들어 int형의 경우 32bit(4byte)이므로 -231~ 231-1의 범위를 갖는다. 210=1024≒103이므로 231=210*210*210*2 = 1024 * 1024 * 1024 * 2 ≒ 2 * 109 따라서, int형은 대략 9자리수(약 2,000,000,000)의 값을 저장할 수 있다는 것을 알 수 있다. 9자릿수에 가까운 자리수(7자리나 8자리)의 수를 계산할 때는 넉넉하게 long형(약 19자리)을 사용하는 것이 좋다. 연산 중에 저장범위를 넘어서게 되면 원하지 않는 값을 결과로 얻게 될 것이기 때문이다. 정수형에서 int를 실수형에서는 float를 주로 사용하므로, int와 float의 범위를 기억해서, int와 float의 범위를 넘는 값을 다뤄야 할 때 long과 double을 사용하면 된다. 기본 자료형의 크기를 쉽게 외우는 방법은 다음과 같다.
2.2 논리형 - boolean 논리형에는 boolean, 한가지 밖에 없다. boolean형 변수에는 true와 false 중 하나를 저장할 수 있으며 기본값(default)은 false이다. boolean형 변수는, 대답(yes/no), 스위치(on/off) 등의 논리구현에 주로 사용된다. 그리고, boolean형은 true와 false, 두 가지의 값만을 표현하면 되므로 기본형 중에서 가장 크기가 작은 1 byte이다. [참고] 1 byte는 8 bit이므로 2의 8제곱, 256가지의 값을 표현할 수 있다. 따라서 boolean형은 크기가 1byte이므로 256가지의 값을 표현할 수 있으나, true와 false, 2가지의 값만을 표현하는데 사용되고 있다. 아래 문장은 power라는 boolean형 변수를 선언하고 true로 변수를 초기화 했다.
[주의] Java에서는 대소문자를 구별하기 때문에 TRUE와 true는 다른 것으로 간주하므로 주의하도록 한다. 2.3 문자형 - char 문자형 역시 char 한가지 밖에 없다. 기존의 많은 프로그래밍의 언어에서 문자형의 경우 1 byte(ASCII코드)의 크기를 갖지만, Java에서는 유니코드(Unicode)문자 체계를 사용하기 때문에 크기가 2byte이다. [참고] Unicode는 세계 각 국의 언어를 통일된 방법으로 표현할 수 있게 제안된 국제적인 코드 규약이다. 미국에서 개발되어진 컴퓨터는 그 구조가 영어를 바탕으로 정의되어 있기에 26자의 영문 알파벳과 몇 가지 특수 문자를 표현하기에는 1바이트로 충분하였기 때문에 모든 정보(문자)가 1바이트를 단위로 표현되고 있었으나 동양3국의 언어 표현인 한글, 한자 또는 일어 등과 같은 문자는 그 구조가 영어와 달라서 1 바이트로는 표현이 불가능하기에 2바이트로 조합하여 하나의 문자를 표현하는 컴퓨터의 구조적 문제점을 바탕으로 유니코드가 만들어 졌다. 유니코드에 대한 보다 자세한 내용은 원한다면, http://www.unicode.org을 방문해보도록 하자. [참고]아스키는 128개의 가능한 문자조합을 제공하는 7비트(bit) 부호로, 처음 32개의 부호는 인쇄와 전송 제어용으로 사용된다. 보통 기억장치는 8비트(1바이트, 256조합)이고, 아스키는 단지 128개의 문자만 사용하기 때문에 나머지 비트는 특수문자에 사용된다. char형의 크기는 2 byte이므로 16진수로 0000부터 ffff까지, 문자를 표현하는데 65536개(2의 16제곱)의 코드값을 사용할 수 있으며, char형 변수는 이 범위 내의 코드값 하나를 저장할 수 있다. 예를 들어 알파벳 A의 유니코드값은 0041이다. char형 변수에 문자 A를 저장하려면 아래와 같이 한다.
char형 변수 firstLetter를 선언하고, 문자 A를 저장했다. char형 변수에 문자를 저장할 때는 "(홑따옴표)로 문자를 둘러싼다. 두 번째는 문자의 코드를 이용해서 문자형 변수 firstLetter에 값을 저장했다. 문자형 변수에 값을 저장하는 데는 위의 두 가지 모두 가능하지만, 주로 첫 번째 방식으로 문자를 저장한다. 다음은 char형이 저장되는 방식을 short형과 함께 비교해 보았다. ![]() [표2-4]char형과 short형의 값 비교 char형이나 short형은 크기가 모두 2 byte(16 bit)지만, 범위가 다르다. char형은 0~65535이고 short형은 -32768~32767이다. 하지만, 둘 다 2 byte이기 때문에 표현할 수 있는 수는 65536개로 같다. char형은 문자의 코드값을 저장하므로 음수를 필요로 하지 않기 때문에 2진수로 표현했을 때의 첫 번째 자리를 부호에 사용하지 않는다. 반면에 short형은 첫 번째 자리를 부호를 표현하는데 사용하기 때문에 서로 다른 범위를 갖게 되는 것이다. 이처럼 char형은 정수형과 표현방식이 같기 때문에 정수형과 깊은 관계가 있다. 만일 어떤 문자의 코드값을 알고 싶으면, char형 변수를 정수형(int)으로 변환하면 된다. 어떤 타입(Type, 형)을 다른 타입으로 변환하는 것을 형변환(캐스팅, casting)이라고 하는데, 형변환에 대해서는 후에 자세히 설명하도록 하겠다. 지금은 문자의 코드값을 알아내는 방법과, 어떤 코드가 어떤 문자를 나타내는가를 알아내는 방법이 있다는 정도만 알면 된다.
위의 예제를 실행하면 65가 화면에 출력되는데, 문자 A의 코드가 10진수로 65임을 뜻한다.(16진수로는 41)
이 예제는 코드값 65(16진수로 41)가 어떤 문자를 뜻하는지를 알아낼 수 있는 방법을 알려 준다. [참고] char형은 크기가 2byte이고, 2byte는 16bit이므로 2의 16제곱(65536)개의 값을 저장할 수 있다. 0을 포함하므로 범위는 0~65535, 16진수로는 0x0000~0xffff가 된다. 두 예제에서 볼 수 있듯이 char형의 변수를 정수형(int)으로 변환(casting)하면, 변수에 저장되어 있는 문자의 코드값을 10진수로 얻을수 있다(CharToCode.java). 반대로 한 코드가 어떤 문자를 나타내는지 알고 싶으면, 코드를 정수형 변수에 저장한 다음, char형으로 변환하여 출력하면 된다(CodeToChar.java). 임의로 0~65535사이의 값을 하나 선택한 다음, CodeToChar.java를 이용해서 선택한 코드가 어떤 문자를 뜻하는지를 알아보거나 반복문을 이용해서 유니코드 전체를 출력해 보는 것도 흥미로울 것이다. 10진수로 66(16진수로 42)을 문자형으로 변환하여 출력하면 어떤 문자가 출력될까? [참고]유니코드(Unicode)는 ASCII코드와의 호환을 위해서, 유니코드 코드번호 1부터 128까지의 문자를 ASCII코드의 1부터 128까지의 문자와 동일하게 지정하였다. 영문자 이외에 Tab이나 space 등의 특수문자를 저장하려면 아래와 같이 하도록 한다.
\t는 실제로는 두 문자로 이루어져 있지만, 단 한 문자 Tab을 의미한다. 아래의 표는 Tab과 같이 특수한 문자를 어떻게 표현할 수 있는지 알게 해준다. ![]() [표2-5] 특수문자
char형 변수는 단 하나의 문자 밖에 저장할 수 없기 때문에 여러 문자를 저장하기 위해서는 String클래스를 사용해야한다.
원래 String은 클래스이므로 연산자 new를 사용해서 String name = new String("Java");와 같이 해야 하지만, 특별히 위와 같은 표현도 허용한다. 그리고, 자바에서는 덧셈 연산자를 이용해서 문자열을 결합할 수 있도록 허용하기 때문에 위의 문장을 아래와 같이 할 수도 있다.
피연산자 중 어느 한 쪽만 String이면 나머지 한 쪽을 먼저 String으로 변환한 다음 결합하는 성질을 갖고 있어서, 예들 들면 수식 7 +"7"을 계산할 때 7이 String이 아니므로 7을 String으로 변환한 다음 "7" + "7"을 수행하여 "77"을 결과로 얻는다. ![]() [표2-6]문자열과 기본형의 덧셈연산 [참고]문자열에 대한 내용은 뒷부분에서 자세히 다룰 것이다.
2.4 정수형 - byte, short, int, long 정수형에는 모두 4개의 자료형이 있는데, 크기순으로 나열하면 아래와 같다.
크기는 byte부터 long까지 1 byte부터 시작해서 2배씩 증가하며, 이 4개의 정수형 중에서 기본 자료형(default)은 int이다. 변수에 저장하려는 정수값의 범위에 따라서 4개의 정수형 중에서 하나를 선택하면 되겠지만, byte나 short 보다는 int를 사용하도록 한다. byte와 short이 int보다 크기가 작아서 메모리를 조금 더 절약할 수는 있지만, 범위가 작은 편이라서 연산 시에 범위를 넘어서 뜻밖의 결과를 얻기가 쉽다. JVM의 피연산자 스택(Operand Stack)이 피연산자를 4 byte단위로 저장하기 때문에 크기가 4byte보다 작은 자료형(byte, short)값을 계산할 때는 항상 4byte로 변환하여 연산이 수행된다. 그래서 특별한 경우를 제외하고는 정수형 변수의 타입으로 int를 사용한다. 정수형 변수의 선언과 초기화는 다음과 같이 한다.
10진수이외에도 16진수 또는 8진수로 표현된 정수값을 변수에 저장할 수 있다. 16진수 임을 표시하기 위해서 값앞에 접두사 0x 또는 0X를(0은 숫자), 8진수 임을 표시하기 위해서는 0(숫자)를 붙인다.
byte형을 예를 들면, byte형 변수의 크기는 1 byte이므로 8 bit이다. 8 bit이므로 8자리의 0과 1을 표현할 수 있다. [그림2-1] byte의 2진표현 1 byte는 모두 8개의 자리수를 가지며, 각 자리수는 0 또는 1 값을 가질 수 있다. 따라서 1 byte로는 모두 2의 8제곱(256)가지의 값을 표현할 수 있다. 그리고, 정수는 0을 포함한 양수와 음수로 이루어져 있으므로, 8개의 자리수 중에서 왼쪽에서 첫번 째 자리수를 부호자리수(sign bit)로 사용한다. 실제로 값을 표현할 수 있는 자리수는 모두 7개 따라서 ±27개가 되는 것이다. 그런 이유로 byte형 변수가 가질 수 있는 값의 범위가 -128~127(-27~27-1)인 것이다.
이전에 언급한 것과 같이 byte형으로 표현할 수 있는 값의 범위는 -128~127(-27~27-1)라고 했다. 위의 예제를 보면, byte형 변수 b의 값이 0부터 시작해서 1씩 계속 증가하여 300이 되어야 한다. 하지만, b가 표현할 수 있는 양의 정수값의 범위는 127까지 인데, 300까지 값이 증가되면 어떤 일이 일어날까? byte가 저장할 수 있는 범위를 넘어섰기 때문에 overflow가 발생하게 된다. 그러나, 위의 예제를 실행해보면 알겠지만, 에러없이 잘 실행된다. 다만 여러분이 원했던 결과가 나오지는 않을 것이다. 위의 예제에서 원하는 결과를 얻으려면 byte보다 큰 정수형 변수를 사용해야 할 것이다. 전에도 언급했던 것과 같이, 이 경우에는 int형 변수를 사용하는 것이 더 바람직하다. ![]() [표2.5]byte의 overflow 자동차의 주행표시기와 같이 최대값을 넘어서면 다시 최소값부터 반복되게 된다. 만일 세 자리 숫자의 주행표시기라면 000부터 시작해서 999까지 밖에 표현을 못하므로 999 다음의 숫자는 다시 000이 될 것이다. byte형의 경우 -128(최소값)부터 시작해서 127(최대값)을 넘으면 다시 -128부터 시작하게 된다. 즉, 256을 주기로 값이 계속 반복된다. 나머지 다른 정수형들도 이와 같은 방식으로 처리된다. 나머지 정수형 타입들인 short, int, long 역시 저장할 수 있는 값의 범위를 넘는 경우 byte와 같은 방식으로 값의 overflow가 이루어진다. 하지만, 아래와 같이 초기화 할 때에는 컴파일시에 에러가 발생한다.
2.5 실수형 - double 실수형에는 float와 double, 두 가지가 있으며, 실수 즉 부동소수점 수(floating-point number)를 다루기 위해 제공되는 자료형이다. float와 double의 크기는 각각 4 byte와 8 byte로 int와 long의 크기와 같지만, 정수형과는 다른 저장방식 덕분에 훨씬 더 큰 범위의 값을 표현할 수 있다. 부동소수점 방식은 수를 정수형과 같은 단순한 2진 표현이 아닌 a ×10n 제곱형태로 표현한다. 즉, 값을 부호(S), 가수(M), 지수(E) 세 부분으로 나누어 표현한다. 예를 들어 3000000을 3×106과 같이 표현할 수 있으며, 여기서 가수는 3이고 지수는 6이 된다. 여기서 가수는 5이고 지수는 6이 된다. 하지만, 이것은 어디까지나 10진 표현이고 2진 표현으로는 a×2n 와 같이 표현한다. 단, 1≤ a < 2 이어야 한다.
[그림2-2]실수형의 값을 저장하는 방식 위의 그림에서 괄호 안의 숫자는 할당된 자리수이다. 가수(M)를 표현하는데 있어서 float에 비해서 double이 약 두 배의 자리수가 배정되어 있기 때문에 float보다 double이 정밀도(소수점이하의 자리수)가 더 높은 값을 표현할 수 있다는 것을 알 수 있다. 따라서 float와 double중 어느 자료형을 사용하는가 결정하는데 있어서 값의 범위만이 아닌 정밀도도 중요한 요소가 된다. float로는 가수를 10진수로 8자리 정도 밖에 표현할 수 없기 때문에 보다 높은 정밀도를 요구하는 계산에서는 double을 사용하도록 한다.
float형 변수 f2에 0.100000001f을 저장하였음에도 불구하고 0.1이 출력된 이유는 0.100000001f이 float가 표현할 수 있는 가수의 자리수(정밀도)를 넘어서는 것이기 때문이다. 같은 값을 저장한 double형 변수 d2는 가수의 자리수가 float보다 약 2배정도 많기 때문에 값을 정확히 표현할 수 있었다. [참고]float와 double의 값 표현 방식은 IEEE754의 정의를 따른다. 보다 자세한 내용은 http://c.ddart.net/datatype/float/ieee754notation/ieee754/ie4.html을 참고하도록 한다. 실수형의 리터럴에는 접미사 f 와 d가 대소문자 구별없이 사용되는데 f는 float형 리터럴에 사용되고, d는 double형 리터럴에 사용된다.
정수형에서는 int형이 기본형이듯 실수형에서는 double형이 기본형이다. 따라서 접미사를 생략하게 되면 double형 리터럴로 간주된다.
위 문장의 3.14는 접미사가 붙지 않았으므로 float형 리터럴이 아닌 double형 리터럴로 간주된다. 그래서, 위의 문장은 컴파일 에러가 발생한다. 컴파일 에러를 피하려면, 3.14f와 같이 float형 리터럴로 변경해주면 된다. [참고]리터럴에 접미사가 붙는 자료형은 long, float, double 뿐인데, double은 생략 가능하므로 long과 float의 리터럴을 표현할 때만 접미사 붙이는 것을 잊지 않으면 된다. 리터럴에 소수점이나 10의 제곱을 나타내는 E 또는 e, 그리고 접미사 f, F, d, D를 포함하고 있으면 실수형 리터럴로 간주된다. [표2-8]실수형의 리터럴 표현 [참고]e, E는 숫자와 함께 사용되어야하며 단독적으로는 사용될 수 없다. [참고]리터럴(literal)이란, 그 자체가 데이터를 의미하는 숫자 또는 기호를 말한다. 예를 들면, 123, "A", 10.0f 등은 모두 리터럴이다. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
다음검색
댓글
댓글 리스트-
작성자후지산정복D-1 작성시간 06.04.18 int a = 1; 이 한 라인이 의미하는 바를 100% 이해한다면 프로그래밍 반을 배웠다고 해도 과언이 아닐만큼 변수에 대한 내용은 무척이나 중요합니다. ^^;
-
작성자후지산정복D-1 작성시간 06.04.18 참고로 영어나 숫자같은 경우는 1바이트이고 특수문자(예외로 1바이트 특수문자 있슴)나 한글, 일어의 히라가나, 한자, 가타카나(전각)는 2바이트로 구분된답니다. ^^;
-
작성자열혈라르끄 작성시간 06.08.22 음.. 일단 패스~!
-
작성자BS 라즈니쉬 작성시간 06.09.03 프로그래밍에 길은 멀고도 험하군요....
-
작성자초리장군 작성시간 07.04.18 예제 2-6 실행결과 첫번째줄에서 1.2345679 라고 나오는데요...8이 없는 이유가 궁금합니다.




[그림2-2]실수형의 값을 저장하는 방식