ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [스터디 2주차] 자바 데이터 타입, 변수 그리고 배열
    프로그래밍 언어/JAVA 2021. 5. 26. 18:44
    더보기

    오늘의 목표: 자바의 프리미티브 타입, 변수 그리고 배열을 사용하는 방법을 익힙니다.

    1. 프리미티브 타입 종류와 값의 범위 그리고 기본 값

    프리미티브 타입 종류를 알아보기 전에 프리미티브 타입이 무엇인지 알아보자.

    프리미티브 타입(primitive type)은 기본(원시) 형태를 의미하며 오늘 알아볼 것은 자바에서 사용하는 데이터의 기본 형태인 primitive type을 알아보는 것이다.

    하나의 값(데이터)를 저장할 수 있는 메모리의 공간을 의미하는 변수(variable)는 타입(일정한 형태)이 있고 이 타입에 따라 변수에 저장할 수 있는 값의 종류와 범위가 달라진다.

    변수를 선언할 때 그 안에 저장할 값이 어떠한 데이터 타입을 가질지 같이 선언해주므로 데이터 타입의 기본형(원시형)인 primitive type을 알아볼 필요가 있다.

     

    기본타입(primitive type)이란 정수, 실수, 문자, 논리 리터럴을 직접 저장하는 타입을 말한다.

    직접 저장한다는 것은 값을 할당할 때 변수의 주소값에 값이 그 자체로 저장된다는 것을 의미한다.

    그러면 이제 primitive tpye의 종류, 값의 범위, 기본값에 대해 알아보자.

    값의 종류 기본 타입 메모리 사용 크기 기본값 저장되는 값의 범위
    정수 byte 1 byte 8 bit 0 -2 ^{7} ~ 2 ^{7}-1 (-128 ~ 127)
    short 2 byte 16 bit 0 -2 ^{15} ~ 2 ^{15}-1 (-32768 ~ 32767)
    int 4 byte 32 bit 0 -2 ^{31} ~ 2 ^{31}-1 (-2147483648 ~ 2147483647)
    long 8 byte 64 bit 0L -2 ^{63} ~ 2 ^{63}-1
    문자 char 2byte 16 bit '\u0000' 0 ~ 2 ^{16}-1 (유니코드: \u0000 ~ \uFFFF, 0 ~ 65535)
    실수 float 4 byte 32 bit 0.0f 1.4E-45 ~ 3.4E38 (1.4 x 10^-45 ~ 3.4 x 10^38)
    double 8 byte 64 bit 0.0 4.9E-324 ~ 1.8E308 (4.9 x 10^-324 ~ 1.8 x 10^308)
    논리 boolean 1 byte 8 bit FALSE true, false

     

     

    2. 프리미티브 타입과 레퍼런스 타입

    자바에서 데이터 타입은 위에서 설명한 프리미티브 타입(primitive type, 기본형)과 레퍼런스 타입(reference type, 참조형)으로 나뉜다.

    프리미티브 타입(primitive type, 기본형)에 대해 정리해보면 다음과 같다.

    - 총 8가지의 기본형 타입을 java에서 미리 정의하여 제공한 것이다.

    - 기본값이 존재하기 때문에 null값이 존재하지 않고 기본형에는 null값을 저장할 수 없다.

    (만약, 기본형에 null값을 저장하고 싶다면 wrapper 클래스를 사용하면 가능해진다.)

    - 실제 값을 저장하는 공간으로 JVM Runtime Data Area에서 스택에 저장된다.

     

    다음으로 레퍼런스 타입(reference type, 참조형)은 다음과 같다.

    - 자바에서 정의한 기본형을 제외한 타입들이 레퍼런스 타입(reference type, 참조형)이다.

    - 기본형과 달리 null값이 존재할 수 있다.

    - 값이 저장되어 있는 곳의 주소값을 저장하는 공간으로 JVM Runtime Data Area에서 힙(heap)에 저장된다.

    - 변수 선언 시에 데이터의 크기가 정해져 있지 않고 변수가 할당될 때에는 저장할 메모리 공간의 주소가 저장되어 진다.

    (즉, 실제 데이터는 heap영역에 존재하고 stack영역에서 데이터가 저장된 공간을 알려주는 주소 값이 저장된다.)

    - 참조형의 예로는 클래스 타입, 인터페이스 타입, 배열 타입, 열거 타입 등이 있다.

     

    프리미티브 타입(primitive type, 기본형)과 레퍼런스 타입(reference type, 참조형)의 차이점을 보면

    프리미티브 타입(primitive type, 기본형)은 메모리상에 할당되는 각각의 공간에 실제 값이 들어가고

    레퍼런스 타입(reference type, 참조형) 다른 것을 참조하기 위한 주소값이 들어가있다.

     

     

    3. 리터럴 (Literal)

    리터럴(literal)이란 소스 코드 내에서 직접 입력된 값을 뜻한다.

    int var1 = 1;
    char var2 = '가';

    즉, 위 소스 코드를 보면 int형이고 변수이름이 var1인 변수에 1이라는 데이터를 저장한다.

    여기서 1이라는 값이 리터럴(literal)이 되는 것이고 두번째 줄 코드를 보면 '가'라는 값이 리터럴이 되는 것이다.

    리터럴은 상수와 같은 의미이지만, 프로그램에서 상수를 "값을 한 번 저장하면 변경할 수 없는 변수"로 정의하기 때문에 상수랑 구분하여 사용하는 용어가 필요하기 때문에 리터럴이라는 용어를 사용한다.

    리터럴은 값의 종류에 따라 정수 리터럴, 실수 리터럴, 문자 리터럴, 논리 리터럴로 구분된다.

    그러면 지금부터 하나씩 알아보도록 하자.

    1) 정수 리터럴

    정수 리터럴을 저장할 수 있는 데이터 타입은 byte, char, short, int, long 5가지가 있다.

    byte, short, int, long은 정수 값을 저장하기 때문에 정수 리터럴이 된다는 것은 이해되지만

    char은 어떻게 정수 리터럴을 저장할 수 있는 데이터 타입일까?

    그 이유는 char이라는 데이터 타입으로 선언된 변수에는 작은 따옴표(')로 감싼 문자뿐만 아니라 직접 유니코드 정수값으로 저장할 수 있기 때문이다.

    예를 들어, 문자 A는 유니코드로 10진수는 65, 16진수는 0x41이다.

    그러면 소스 코드에서

    char c1 = 'A';
    char c2 = 65;
    char c3 = '\u0041';

    으로 변수에 리터럴 값을 넣어주면 c1, c2, c3 모두 System.out.println()으로 출력 값을 보면 A로 출력되는 것을 볼 수 있다.

     

    소수점이 없는 정수 리터럴은 10진수로 간주사고 0으로 시작하는 리터럴은 8진수로 간주하고

    0x 또는 0X로 시작하고 0~9숫자나 A,B,C,D,E,F 또는 a,b,c,d,e,f로 구성된 리터럴은 16진수로 간주한다.

     

    2) 실수 리터럴

    정수 리터럴을 저장할 수 있는 데이터 타입은 float, double이 있다.

    소수점이 있는 리터럴은 10진수 실수로 간주하고 대문자 E 또는 소문자 e가 있는 리터럴은 10진수 지수와 가수로 간주한다.

     

    3) 문자 리터럴

    정수 리터럴을 저장할 수 있는 데이터 타입은 char이 있다.

    작은 따옴표(')롤 묶은 텍스트는 하나의 문자 리터럴로 간주한다.

    역슬래쉬('\')가 붙은 문자 리터럴은 이스케이프(escape)문자라고 하는데 여러 이스케이프 문자와 그 용도에 대해 간단하게 표로 설명해보겠다.

    이스케이프 문자 용도
    '\t' 수평 탭, 간격을 탭만큼 벌리고 싶을 때 사용한다.
    '\n' 줄 바꿈
    '\r' 캐리지 리턴(CarriageReturn), 커서를 행의 앞으로 이동
    '\"' "(큰 따옴표) 자체를 의미
    '\'' '(작은 따옴표) 자체를 의미
    '\\' 백슬래쉬 자체를 의미
    '\u16진수' 16진수에 해당하는 유니코드를 나타낼 때 사용

     

    4) 논리 리터럴

    정수 리터럴을 저장할 수 있는 데이터 타입은 boolean이 있다.

    true와 false를 논리 리터럴로 간주한다.

     

     

    4. 변수 선언 및 초기화하는 방법

    변수를 사용하기 위해서는 변수를 선언해야하는데 변수 선언은 어떤 타입의 데이터를 저장할 것인지와 변수 이름을 무엇으로 할 것인지를 결정한다.

    타입은 변수에 저장되는 값의 종류와 범위를 결정짓는 요소이다.

    변수이름은 메모리 주소에 붙여지는 이름으로 프로그램은 변수 이름을 통해 메모리 주소에 접근한다.

    같은타입의 변수는 콤마(,)를 이용해서 다음과 같이 한꺼번에 선언할 수 있다.

    char v1, v2, v3;

    변수 이름을 선언할 때에는 자바에서 정한 naming convention을 따라야하고 다음과 같다.

    - 첫 번째 글자는 문자이거나 '$', '_'이어야 하고 숫자로 시작할 수 없다.

    - 영어 대소문자가 구분된다.

    - 갈이의 제한은 없다.

    - 자바 예약어(boolean, byte, super, null, return등)는 사용할 수 없다.

     

    변수 초기화(initialization)는 변수에 초기값을 주는 행위를 뜻한다.

    변수를 초기화하는 방법은 다음과 같다.

    // 변수 선언 후, 초기화 가능
    int var1;
    var1 = 90;
    
    // 변수 선언과 동시에 초기화 가능
    int var2 = 90;

     

     

    5. 변수의 스코프와 라이프타임

    변수 스코프는 프로그램 내 변수에 접근할 수 있는 유효 범위/영역을 뜻한다.

    즉, 소스 코드 내에 많은 변수가 선언되어있어도 이 변수들을 접근 할 수 있는 범위(영역)이 정해져 있다는 것이고 이를 변수의 스코프라고 말하는 것이다.

    class class1 {
        int var1; /*인스턴스 변수*/
        static in var2 ; /*클래스 변수*/
        
        void method(){
        	int var3 ; /*지역 변수*/
        }
    }

    변수는 위와 같이 중괄호 {}블록 내에서 선언되고 변수의 스코프는 키워드와 선언된 블록위치에 따라 달라진다.

     

    클래스 내부에 선언되는 변수를 멤버변수라고 부르고 메서드 내부에 선언되는 변수를 지역변수라고한다.

    변수의 종류 선언위치 생성시기
    클래스 변수 클래스 영역 클래스가 메모리에 올라갈 때
    인스턴스 변수 인스턴스가 생성될 때
    지역 변수 클래스 영역 이외 (메소드, 생성자, 초기화 블록) 변수 선언문이 수행될 때

     

    변수 라이프타임(lifetime)은 변수가 메모리에서 언제까지 살아있는지를 나타낸다.

    클래스 변수의 경우, 클래스가 초기화되고 프로그램이 끝날 때까지가 라이프타임이고

    인스턴스 변수는 객체가 생성되고 객체가 메모리에 살아있는 동안이 라이프타임이고

    지역 변수는 변수 선언 이후부터 블록을 벗어날 때까지가 라이프타임이다.

     

     

    6. 타입 변환, 캐스팅 그리고 타입 프로모션

    타입 변환은 데이터 타입을 다른 데이터 타입으로 변환하는 것이다.

    int 데이터 타입으로 선언된 변수를 byte 타입으로 변환하거나 float 데디터 타입으로 선언된 변수를 double 타입으로 변환하는 것을 말한다.

    타입 변환은 자동 타입 변환(Promotion)과 강제 타입 변환(Casting) 두 종류가 있다.

    Promotion과 Casting에 대해 자세히 알아보자.

     

    자동 타입 변환(Promotion)

    자동 타입 변환(Promotion)은 프로그램 실행 중에 자동적으로 타입 변환이 일어나는 것이다.

    자동 타입 변환이 일어나는 경우는 작은 크기를 가지는 타입이 큰 크기를 가지를 타입에 저장될 때 발생한다.

    여기서 말하는 큰 크기와 작은 크기는 사용하는 메모리 크기를 통해 나뉘는 것이다.

    크기별로 타입을 정리하면 다음과 같다.

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

    float 데이터 타입이 사용하는 메모리 크기가 4bytes이지만 int와 long 타입보다 큰 이유는 표현할 수 있는 값의 범위가 더 크기때문이다.

    자동 타입 변환(Promotion)이 일어나는 예시를 보자.

    byte var1 = 15;
    int var2 = var1;

    byte 타입으로 선언된 var1의 값을 int 타입인 var2로 대입하면 var1은 자동으로 int 타입으로 자동 타입 변환이 된다.

     

    강제 타입 변환(Casting)

    강제 타입 변환은 강제적으로 큰 데이터 타입을 작은 데이터 타입으로 쪼개어 저장하는 것을 말한다.

    강제 타입 변환은 캐스팅 연산자 ( )를 사용하고 괄호 안에 들어가는 타입은 쪼개는 단위이다.

    예시를 보자.

    int var1 = 103029770;
    byte var2 = (byte) var1;

    원래는 int 타입은 4bytes를 사용하고 byte는 1bytes를 사용하므로 var1을 var2에 저장할 수 없다.

    하지만 이러한 부분을 해결하기 위해 강제 타입 변환으로 캐스팅 연산자인 (byte)를 사용해서 var1을 1byte씩 쪼개어 끝에 있는 1byte만 var2에 저장한다.

    강제 타입 변환 메커니즘

    끝 1byte만 var2에 저장되므로 원래 var1값은 보존되지 않는다.

    만약 int 데이터 타입인 변수의 값이 끝 1byte로만 표현이 가능하다면, byte타입으로 변환해도 값이 보존된다.

    실수 타입(float, double)의 경우 정수 타입(byte, short, int, long)으로 자동 변환되지 않기 때문에 강제 타입 변환을 사용해야 한다.

    실수 타입을 정수타입으로 강제 타입 변환을 한다면 소수점 이하 부분은 버려지고 정수 부분만 저장된다.

     

     

    7. 1차 및 2차 배열 선언하기

    배열은 동일한 타입의 연관된 데이터가 메모리에 연속적으로 저장되어 하나의 변수로 관리하기 위한 자료 구조이다.

    배열의 길이(크기)는 배열을 처음 선언할 때 고정되어진다.

    배열의 선언 방법은 2가지가 있다.

    데이터 타입 [ ] 변수이름;
    데이터 타입 변수이름 [ ];

    이처럼 배열을 선언할 때 변수만 선언하고 크기 및 값은 나중에 초기화하는 것이 가능하다.

    int [] arr1 = new int[10]; /* 배열 크기 할당 */
    double [] arr2 = new double[] {1.1, 2.2, 3.3, 4.4}; /* 배열 초기화 */

    또한, 위의 경우처럼 배열 선언 시에 배열의 크기 및 값을 할당해주는 것도 가능하다.

    여기서 new연산자를 사용해 배열의 타입과 길이를 지정하면 메모리에 해당 길이만큼 영역을 확보한다.

    배열의 길이는 초기화 시에 선언한 길이에서 정적이므로 길이의 변경을 원할 때는 새로운 배열을 생성해야한다.

     

    지금까지 예시로 본 것은 1차 배열 선언이다.

    배열은 1차 배열 뿐만 아니라 2차, 3차 등 다차원 배열도 선언이 가능하다.

    선언방법의 차이는 대괄호[ ]의 갯수 차이로 대괄호가 1개이면 1차원, 2개이면 2차원, n개이면 n차원으로 메모리가 허용가능한 범위까지 다차원을 선언할 수 있다.

     

     

    8. 타입 추론, var

    타입 추론은 코드 작성 시에 데이터 타입이 정해지지 않았지만 컴파일러가 데이터 타입을 유추하는 것을 말한다.

    var는 자바 10버전부터 추가된 타입 추론을 지원하는 키워드이다.

    var 키워드는 지역변수이면서 선언과 동시에 초기화가 필수적으로 요구된다.

     

     

     

    댓글

Designed by Tistory.