본문 바로가기

Programming/Java

[기본-2]자바 데이터 타입, 변수 그리고 배열

목표

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

목차

  • 프리미티브 타입 종류와 값의 범위 그리고 기본 값
  • 프리미티브 타입과 레퍼런스 타입
  • 리터럴
  • 변수 선언 및 초기화하는 방법
  • 변수의 스코프와 라이프타임
  • 타입 변환, 캐스팅 그리고 타입 프로모션
  • 1차 및 2차 배열 선언하기
  • 타입 추론, var

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

구분 타입 크기 범위 기본값 비고
논리형 boolean 1byte false 또는 true false  
문자형 char 2byte '\u0000' ~ '\uFFFF' '\u0000'  
정수형 byte 1byte -2^7 ~ 2^7 - 1 0 -128 ~ 127
short 2byte -2^15 ~ 2^15 - 1 0  
int 4byte -2^31 ~ 2^31 - 1 0 정수형 타입의 기본형
long 8byte -2^63 ~ 2^63 - 1 0L  
실수형 float 4byte 약 1.4E-45~.3.4E38 0.0f 권장하지 않음
double 8byte 약 4.9E-324 ~ 1.8E308 0.0d 실수형 타입의 기본형

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

자바에서는 자료형이 크게 프리미티브 타입과 레퍼런스 타입으로 나뉜다. 프리미티브 타입은 위에서 언급한 8가지 타입이 해당되며 이외는 레퍼런스 타입에 해당한다.

 

프리미티브 타입 변수에는 자료형의 값 자체를 저장하며, 레퍼런스 타입은 객체가 위치한 주소값을 갖는다.

프리미티브 타입과 레퍼런스 타입의 메모리 영역 비교

프리미티브 타입은 스택 영역에 변수와 값을 가지게 된다. 반면 레퍼런스 타입의 경우를 예를 들면 Book 이라는 클래스가 있다고 가정한다. Book b 라는 변수는 스택영역에 생성되고 실제 객체는 Heap 메모리 영역에 저장된다. b는 Book객체의 객체를 직접적으로 갖지 않고 Book 객체에 대한 참조를 가진다.

3. 리터럴

리터럴이란 값 자체를 의미하며 다음 예제를 통하여 이해할 수 있다.

int a = 3; // 숫자 리터럴 3
boolean b = true; // 논리 리터럴 true
char c = 'A'; // 문자 리터럴 대문자 A
double d = 3.14; // 실수 리터럴 3.14
String s = "Hello"; // 문자열 리터럴 Hello

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

변수 선언과 값할당은 동시에 할 수도 있다.

int a; // 변수 선언
a = 10; // 값 할당
int b = 20; // 변수 선언과 값 할당 

//레퍼런스 타입의 생성 및 할당의 예
List<Integer> list = new ArrayList<>(); // new 키워드를 사용하여 객체를 생성한다.

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

변수의 스코프에 대해서 정리하고자 한다. 다음은 지역 스코프에 대한 예제이다.

public int sum(int a, int b) {
    int c = a + b; // 변수 c의 경우 sum이라는 함수 내에서만 접근 가능하다. 블록 바깥에서 해당 변수로 접근할 수 없고, 해당 블록이 처리된 후 c는 소멸된다.
    return c;
}

 

 

클래스 안에 선언된 필드는 기본적으로 같은 클래스 내에서 접근 가능하다. 

public class Book {
    private int id;
    private String name;
    
    public String getName() {
        return name; // 함수 내에서 바깥에 존재하는 name에 접근이 가능하다.
    }
}

 

스코프에 대한 설명의 연장선으로 static 블록과 default 블록에 대해서 설명하고자 한다. static 블록은 객체가 메모리에 할당될 때 최초로 실행되는 블록이며, default 블록은 객체가 생성될 때마다 호출되는 블록이다. 생성자와 비슷하지만 생성자의 경우는 파라메터가 없는 기본생성자 뿐만 아니라 파라메터가 여러개인 생성자가 있을 수 있기 때문에 각각의 생성자에  


public class Scope {

    public static void main(String[] args) {

        System.out.println("첫번째 Book 생성전");
        Book b1 = new Book();
        System.out.println("첫번째 Book 생성후");

        System.out.println("두번째 Book 생성전");
        Book b2 = new Book(1, "자바 프로그래밍");
        System.out.println("두번째 Book 생성후");
        
        /* 실행결과
         * 첫번째 Book 생성전
         * [static 블록]은 메모리에 로딩될 때 최초로 실행됨
         * [default 블록]은 객체가 생성될 때 마다 기본적으로 수행되는 블록이며
         * 저는 어떤 생성자를 호출하던 지 객체가 생성될 때마다 항상 호출됩니다.
         * 기본생성자 호출
         * 첫번째 Book 생성후
         * 두번째 Book 생성전
         * [default 블록]은 객체가 생성될 때 마다 기본적으로 수행되는 블록이며
         * 저는 어떤 생성자를 호출하던 지 객체가 생성될 때마다 항상 호출됩니다.
         * 파라메터가 존재하는 생성자 호출
         * 두번째 Book 생성후
         */
        
        
    }

}

class Book {
    private int id;
    private String name;

    // static block
    static {
        System.out.println("[static 블록]은 메모리에 로딩될 때 최초로 실행됨");
    }

    // default block
    {
        System.out.println("[default 블록]은 객체가 생성될 때 마다 기본적으로 수행되는 블록이며");
        System.out.println("저는 어떤 생성자를 호출하던 지 객체가 생성될 때마다 항상 호출됩니다.");
    }

    public Book() {
        System.out.println("기본생성자 호출");
    }

    public Book(int id, String name) {
        this.id = id;
        this.name = name;
        System.out.println("파라메터가 존재하는 생성자 호출");
    }

    public String getName() {
        return name;
    }
}

실행순서는 static 블록 -> default 블록 -> 생성자 순서로 실행된다.

 

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

형변환

자바에서 형변환이 필요할 경우 다음과 같이 작성할 수 있다.

char c = 'A';
int i = (int)c; // 대문자 A의 아스키코드 값인 65가 저장됨

* 레퍼런스 타입에서도 상속이나 구현관계끼리는 형변환이 가능하다.

 

묵시적 형변환

작은 타입에서 큰 타입으로 변수에 대입할 경우 자동으로 큰 타입으로 형변환이 발생하는 데, 이를 묵시적 형변환이라고 한다. 

int i = 3;
long l = i; // 묵시적 형변환이 발생한다.

묵시적 형변환을 타입프로모션이라고도 한다.

 

 

명시적 형변환

큰 타입에서 작은 타입으로 변수에 대입할 경우 명시적으로 형변환을 하여야 한다. 그렇지 않으면 구문오류가 발생한다. 명시적 형변환을 캐스팅이라고 한다.

//float f = 10.13; // double형이 기본이므로 해당 구문은 에러
float f = (float)10.13; // 또는 float f = 10.13f; 로 작성하여야 한다.

int보다 작은 타입의 정수형 데이터 연산 시 결과값이 기본적으로 int형으로 반환된다.

byte b1 = 10;
byte b2 = 4;
byte b3 = b1 - b2; // 해당 결과는 int형으로 반환되므로 (1)명시적 형변환을 하거나 (2) byte형이 아닌 int형으로 받아야 한다.

 

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

int[] a = new int[5]; // 길이가 5인 int형 배열 생성
int[] b = {1, 2, 3, 4, 5}; // 1차원 배열 선언과 값할당

a[0] = 3; // 값 대입
int c = a[0]; // 객체 원소에 접근하여 값 꺼내기

a.length; // 배열 a의 길이는 5 
//a[5]; // ArrayIndexOutOfBoundsException 발생 (배열은 0부터 시작하여 length - 1 만큼의 공간을 갖는다.)

int[][] d = new int[5][5]; // 2차원 배열 생성
int[][] e = {{1,2,3},{4,5,6},{7,8,9}}; // 2차원 배열 선언과 값할당

for(int i=0; i<e.length; i++) {
    for(int j=0; j<e[i].length; j++) {
       	System.out.println(e[i][j]); // 원소에 접근하여 값 확인
    }
}

 

 

8. 타입 추론, var

jdk 10부터 var 키워드가 추가되었다. 지역 변수일 때 사용가능하고, 선언과 초기화(할당)을 동시에 해줘야 사용 가능하다.

var list = new ArrayList<String>(); 
var stream = list.stream(); 

 

 

참고

- primitive type : docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html

- JEP 286(Local-Variable Type Inference) : openjdk.java.net/jeps/286

'Programming > Java' 카테고리의 다른 글

[기본-6] 상속  (0) 2021.03.03
[기본-5] 클래스  (0) 2021.03.03
[기본-4] 제어문  (0) 2021.03.02
[기본-3]자바 연산자  (0) 2021.03.01
[기본-1]JVM은 무엇이며 자바 코드는 어떻게 실행하는 것인가  (0) 2021.02.15