ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Java-6] Java 기본 타입 (primitive)
    Java 2020. 11. 16. 20:21

     

    자 이제 자바의 데이터 타입과 변수 및 배열에 대해서 설명하는 시간을 가져보도록 하자. 프리미티브 타입이란걸 알아 보기전에 타입은 알겠는데, 프리미티브는 뭘까 할 수 있다. 

     

    1. 타입은 알겠는데 프리미티브 타입은 뭐야?

     

    구글 번역기를 돌리면 프리미티브란 단어는 ‘원어' 라는 뜻을 가지고 있다. 자바의 데이터 타입은 2가지로 구성되어있는데, 프리미티브 타입과, 레퍼런스 타입으로 구성되어있다. 이 글에서  이 둘의 차이에 대해서 다루지 않겠다. 먼저 중요한건 프리미티브 타입의 종류와 범위 그리고 기본 값 아닌가?

     

    자 변수의 종류는 무엇이 있을까?

     

    크게 3가지로 나눌 수 있을 것 같은데 정수 타입, 실수 타입, 논리 타입 으로 만들어 있다. 

    먼저 정수 타입에 대해서 얘기해보도록 하자

    2. 정수 타입

     

    정수 타입은 모두 5개의 타입이 정해져 있는데, 그 종류에 대해서 저장할 수 있는 값(value)는 무엇이고, 메모리에 대해서 알아 보도록 하자. 

     

    Byte

     

    바이트는 이진 데이터를 처리할 때 주로 사용한다고 한다. 예를들어, 색상정보를 예를 들 수 있을텐데, RGB 에서 한 색상에 대한 정보값이 8비트다, 자 여기서 알 수 있다. byte의 메모리의 용량은 8bit이고 8 bit는 1Byte 이다.

     

    byte는 1byte의 메모리를 저장 할 수 있는데 이 값은 -2^7 ~ (2^7 - 1) 이다. 10진수로 나타내면 

    -128에서 127인데, 왜 음수의 절대값은 128이고 양수의 절대값은 127일까? 그건 0때문에 양의정수에서 하나를 뺏기 때문이다. : )  

     

     

    그 범위를 표로 작성을 해보면, 

    다음과 같이 정리할 수 있는데 정리하는데 도움이 될 수 있으면 좋겠다.

     

    그럼 범위를 넘으면 어떻게 되는건가?

    컴파일 에러가 발생하는데, 컴파일 에러는 컴파일 시 발생하는 에러를 컴파일 에러라고 하며, 런타임 에러는마이크에 정전기가 흘러들어가서 마이크에서 지지직거리는 소리가 난다면, 런타임 에러라고 할 수 있다. 

     

    왜 컴파일 에러가 발생하는가에 대해서는, 블로그에 Java 컴파일 과정 제 블로그글을 보면 알 수 있습니다.

     

    그럼 만약 byte 변수에 있는 값이 동적으로 변경되다가, 저장할 수 있는 값을 초과되면 어떻게 될까? 궁금해 졌다. 만약 중간에 범위를 넘어가게 되면 제일 하위 값인 -128로 변경이 된다.

     

    이 코드의 값은 어떻게 될까?

    이렇게 변경이 되게 된다. 이를 쓰레기 값이라고 하는데, C에서의 쓰레기 값은 알아 볼 수도 없는 값인데 이런식으로 최하위 단으로 내려가는게 신기했다. 

     

    추가적으로 만약, byte 변수를 선언하고, 아무런 값을 넣지 않는다면 어떻게 될까? 이는 컴파일 에러가 발생한다. byte 의 기본 값은 0 이다. 근데 byte a 를 선언하고, 출력하면 a = 0 이 나와야 하는데 컴파일 에러가 발생한다.

     

     이 부분은 변수 초기화 하는 과정과, 스코프에 대해서 알아볼 때 더 자세히 알아보도록 하자 : )

     

    Char

     

    char는 모든 문자를 저장할 때 사용하는 타입이다. 정확히는 문자뿐만 아니라, 이모티콘도 저장할 수 있긴 할 것이다. 왜냐면 정확히 모든 유니코드를 저장할 수 있기 때문이다. 이 유니코드 라는게 각국의 모든 문자를 코드번호(코드 값)으로 지정해논 규약인데, 여기에는 한글도 들어가있고 알파벳도 들어가 있다. 예를 들어서 

     

    0~127(여기서 범위는 십진수로 나타낸 범위이다.) -> 아스키 코드 (알파벳, 툭수 기호)

    44032~55203 -> 한글 

     

    이런식으로 각 범위마다 지정되어있는 문자가 있다. 이 하나의 유니코드를 저장하는데 필요한 데이터 타입은 char 타입 인 것이다.

     

    자 그럼 이 유니코드의 범위는 어디까지일까? char타입은 유니코드를 담고 있다고 하니, 유니코드의 범위가 즉, char타입의 범위일테니 말이다. 유니코드의 범위는 총 0~65535 이다. 즉, 2^16인데, 이를 바이트 메모리로는 2바이트의 메모리를 가지고 있다. 

     

    char형을 사용하는 방법은 다양한데, 만약에 내가 10진수의 유니코드를 알고 있다면, 문자로 변경할 수 도 있다. 예를들어서 한글 ‘가'의 44032의 유니코드를 가지고 있다. 

    code

     

    그러면 c는 뭐가 출력이 될까?

    결과 console

     

    자 그럼 심심하니, 아까 byte에서 범위를 넘을 때 처럼 char의 범위가 넘을 때는 어떻게 진행이 될까?

    code

     

    유니코드 0의 문자가 뭔지 모르니, 유니코드 0일때의 문자를 출력해주고 같은지 비교해 보도록 하자

    결과 console

    실행하니 다음과 같이 범위를 넘고, 0으로 초기화 된걸 볼 수 있다. 

     

    char의 기본값은 무엇일까 16진로는 \u0000 이고 10진수로는 0으로 기본값이 설정 되어있다.

    code

     

    결과 console

     

    다음과 같은 실행 결과를 가져온다. 

     

    Short

     

    short 타입은 2바이트로 표현되는 정수를 저장하기 위해서 사용하는 데이터 타입인데, 실제 코드를 짜면서 한번도 사용해본적도 없다. 사실 byte도 마찬가지인데, 보통 숫자를 저장하기 위해서는 int를 사용하지 않는가

    게다가 범위는 -32.768~32.767 로 비교적 작은 범위를 가지고있는데, 왜 넣었을까 라는 생각을 하다가 몇가지 이유를 알아 보았다.

     

    일단 C언어의 호환을 위해 사용되었다는 의견도 있으며,

    google 검색 Why use short type in java

    이렇게 검색해보니, 보통 임베디드 코드를 짜거나, low 레벨의 작업을 할 때 많이 사용한다고 한다. 

    In java does anyone use short or byte? 라는 스택 오버플로우의 질문에서 해답을 알 수 있었다. 

     

    따로 short에 대한 코드를 올리지는 않겠다. 

     

    Int

     

    아마 java에서 원시(Primitive)타입에서 가장 많이 사용하는 타입이지 않을까 싶다. int 타입은 4바이트로 지금까지 나왔던 타입보다 꽤나 높은 메모리를 가지고 있다. 저장할 수 있는 값의 범위는 

    -2.147.483.648~2.147.483.647 로 -2^31~(2^31 -1) 이다. 또 양수에서 0을 포함해야 되서 1을 뺀 메모리 용량이다. 

    다음과 같이 4바이트를 1바이트씩 쪼개서 만약에 10이라는 숫자가 들어가면 마지막 1바이트만 10을 2진수로 저장하고 나머지 3바이트는 0으로 변경하게 된다. 

    만약 1바이트로 표현할 수 없는 값이면 2바이트, 2바이트로 표현할 수 없는 값이면 3바이트로, 이런식으로 값을 표현하게 된다.

     

    int 타입은 자바에서 정수를 ‘연산’ 하기위해 만든 타입인데, 이게 무슨소리일까? 정수를 담을 수 있는 타입들은 short도 있고 byte도 있다. 만약에 short + int 가 가능할까? 

     

    가능하다. 하지만 저 연산의 결과를 받는 데이터 타입은 무조건 Int 여야 한다. 즉, short 는 연산을 하기 위해서는 int 를 받아야 된다는 것이다.

     

    그림을 보고 대충 이해가 갔으면 좋겠다.

    그래서 정수를 저장하기 위해서는 보통 int형을 사용하게 된다. int 또한 10진수 16진수 8진수 전부 가능하다. 

     

    Long

     

    다음은 long타입이다. long은 이름에서도 알 수 있듯이 바이트의 수가 원시(primitive)타입에서 double과 함께 제일 많은 메모리 양을 차지 한다. 

    -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807 의 최솟값과 최댓값을 가지고 있는데, 개인적으로 long 타입을 가장 많이 사용할 때는 database의 칼럼과 자바의 필드를 매핑할 때 가장 많이 사용하게 된다.

     

    이제 long 타입은 변수를 선언하고 데이터를 집어넣을 때, 특이한데 예를들어서 int 의 범위를 넘어선 숫자를 입력하게 된다면, 

     

    다음과 같이 Integer number of too large 라는 에러 문구가 뜨게 된다 .

     

    그러면 우리는 이렇게 생각할 수 있다 

    어? 그럼 long타입은 괜찮겠지?

     

    하지만 어림도 없다는 듯이 데이터가 크다고 long타입에 들어가지 못하게 한다. 이유가 뭘까?

     

    기본적으로 자바는 정수를 Int로 취급하게 된다. 그래서 long 타입에 정수를 집어 넣을 때에는, 정수 끝에 접미사로 ‘l’ 또는 ‘L’을 사용하게 된다. 하지만 대문자 L을 추천한다. 왜냐하면 가독성의 문제인데 소문자 ‘l’일 경우 1인지 알파벳 엘인지 알 아보기 어렵기 때문이다. 



     

    그래서 다음과 같이 L을 작성하게 된다.

     

    여기서 궁금한게 만약 접두어 L을 붙히지 않고, long타입을 선언하였고 동적으로 int 범위를 넘는 숫자를 넣게 되면 어떻게 될까?

    int의 범위는 2147483647까지인데, 만약 그 이상의 값을 증가시킨다면, 증가가 될까?

     

     

    이렇게 증가가 된다. 그러므로 걱정은 안해도 될 것 같다. ‘L’을 붙여야 된다는 내용은 Oracle Document에 나와있다. long 의 기본 값은 정수 ‘0L’이다. 



    3.실수 타입

     

    실수 타입이란 무엇일까? 간단하게 알 수 있듯이, 소수점이 있는 실수 데이터를 저장할 수 있는 데이터 타입이다. 즉, 부동 소수점(floating-point)이 있어야 하는데, 부동소수점 방식을 간단하게 얘기를 하자면, 부동소수점은 크게 3가지 형태가 존재하여야 한다.

    예제 1.2345를 보자 1.2345는 + 0.12345 x 10^1 으로 표현되었는데, 기수의 범위는 0<= m < 1의 범위인 실수여야만 한다. 

     

    그럼 이제 이런 부동 소수점 방식으로 되어있는 타입변수에는 무슨 종류가 있을까? 바로 float 형과 double 형이 있다. 이 둘의 차이점에 대해서 얘기해보도록 하자. 먼저 데이터 용량부터 부조마녀, 

    float은 4바이트가 double 형은 8바이트로 구성되어있다. 구성되어있다는 말이 무슨 말이냐면,

    이 부동소수점은 지수와 기수, 부호 구성되어있다고 말을 했다. 각 지수와 기수가 가지고있는 메모리양이 다르다는 의미를 한다. 서론이 길었다. 이 둘의 차이를 표로 알아보도록 하자. 

     

    Float & Double

     

    딱봐도 일단 float은 더블보다 작고, Double은 float에 비해서 2배가량 많은 메모리를 차지 하고있다. 

    그래서 그런지, double의 어원이 float의 메모리의 ‘double’이어서 라고 조심스럽게 생각해본다. 

     

    근데, long 과 int에서도 자바가 기본적으로 정수를 다룰 때는 int형을 다루게 되는데 자바에서 실수를 다룰 때 에는 어떤 타입으로 연산을 할까?

     

    이렇게 자바에서 실수를 기본적으로 double을 인식하게된다. 흠.. 의문이 들기는 한다. 왜 그런걸까 심지어 일관성있게, long보다 더 작은 int를 선택하고, 정수는 왜 float보다 더 큰 double을 택하는 걸까? 이 부분에 의문점이 드는데, 이는 나중에 알아보도록 하자. 아니면 c언어에서 사람들이 int를 더 많이 사용하고, Double을 더 많이 사용하는 ‘관례' 때문일 수도 있겠다.

     

    그러면 float을 사용할 때는 어떻게 사용해야될까? 접두어에 f를 붙히는게 일반적이다.

    이렇게 f 를 접미사에 붙히게 되면 실수를 float 변수 var에 잘 집어 넣을 수 있다. 

     

    무조건 실수만 적지 않아도, 10의지수를 나타내는 e를 통해서도 값을 넣을 수 있다.

    이렇게 다양한 타입으로 나타낼 수 있다. 나는 아무래도 f를 붙여야 한다는 불편함도 있기 때문에 특별한 상황이 아닌 이상 double을 쓰게된다. 궁금해서 float vs double 이란 검색어로 찾아 봤는데, 결국에는 double을 많이 사용한다는 것 같다.

     

    float 과 double의 기본 값은 0.0f 0.0d 이다. double 또한 접미사에 d를 붙일 수 있는데, 안붙혀도 문제가 없다. 

     

    4. 논리 타입

     

    다음은 논리 타입이다. 논리 타입 하니깐 예전에 실수로 클래스와 필드를 선언하고 getter를 자동으로 ide에서 만들어 주거나, @getter 에노테이션을 이용해서 만들었는데, get(필드이름)() 이 아니고 is(논리타입 변수 이름) 인데, 이걸 아무생각없이 하다가 getter가 왜 안되지 하면서 30분 가량을 날린적이 있는데.. 하튼 그런적이 있다. 

     

    Boolean

     

    논리타입에는 boolean이 있는데, 1바이트로 표현되어 저장할 수 있는 값이 true, false로 되어있다. 책에서 별 내용은 따로 없어서, Boolean 타입은 언제부터 생겼을 까 알아보다가 C언어에서는 불리언 타입이 원래 없었다는걸 처음 알았다. 그래서 enum 타입처럼 #define을 정의해서 boolean을 만들었다고 한다...

     

    #define FALSE 0

    #define TRUE 1

    ...

    int f = FALSE;

     

    boolean의 기본값은 false 이다. 자  다시 한번 정리해보자

     

    자바에서 데이터를 집어넣을 수 있는 변수를 선언할 때는 타입을 지정하는데, 그 타입에는 프리미티브 타입과 레퍼런스 타입이 있다. 우리는 그 중에 프리미티브 타입이라는 원시타입에 대해서 알아 본 것이다. 

    이정도에 대해서 알아 보았다. 내용을 정리해보자면

    요로코롬 정리할 수  있을 것 같다. 

     

    > [Java-7] 자바 프리미티타입 , 레퍼런스 타입 & 리터럴 

     

    'Java' 카테고리의 다른 글

    [Java-8] 자바 변수 선언과 초기화  (0) 2020.11.18
    [Java-7] 자바 타입의 종류 & 리터럴  (0) 2020.11.17
    [Java-5] JDK& JRE, 자바 실행  (2) 2020.11.11
    [Java-4] JVM의 구조  (1) 2020.11.11
    [Java-3] JVM과 JIT 컴파일러란?  (2) 2020.11.10

    댓글

Designed by Tistory.