본문 바로가기
👨‍🏫Study/JAVA

[JAVA] 02-2 데이터 타입

by 코푸는 개발자 2021. 8. 2.
728x90

2.2. 데이터 타입 분류

* 각각의 타입들은 표현범위 내의 값을 입력하여 사용해야합니다. (그렇지 않으면 컴파일 에러 발생)

 

String 타입

  • 기본 타입(primitive type)
    • 스택 영역에 그 자체를 저장
    • 정수, 실수, 문자, 논리, 리터럴
  • 참조 타입(reference type)
    • 객체의 번지를 참조하는 타입
      • 스택 영역에 참조변수만 저장
      • 실제 내용은 힙 영역에 저장
    • 배열, 열거, 클래스, 인터페이스

2.2.1. 기본 타입의 메모리 영역

  • 변수와 내용이 스택 영역에 저장된다.

 

2.2.2. 참조 타입의 메모리 영역

  • 참조변수는 스택영역에 저장되어 힙 메모리의 주소를 저장한다.
  • 실제 참조변수가 가리키는 내용은 힙메모리에 저장된다.

 

2.3. 메모리 사용 영역

JVM은 운영체제에서 Runtime Data Area 메모리 영역을 할당받아 다음과 같이 세부 영역으로 구분해서 사용한다.

2.3.1. 힙 영역 (Heap Area)

  • 배열과 객체를 저장하는 영역이다.
  • 이 영역에서 생성된 배열과 객체의 주소를 참조 변수가 갖고 있다.
    • 생성된 배열, 객체를 참조화는 참조 변수가 사라지면 생성되었던 해당 힙 영역은 JVM Garbage Collector에 의해 제거된다

2.3.2. JVM 스택 영역 (JVM Stack Area)

  • JVM 스택 영역은 각 쓰레드마다 하나씩 할당된다.
  • 쓰레드를 만들지 않으면 1개의 main 쓰레드만 존재하며, JVM 스택 영역도 1개이다.
  • 메소드 호출 시마다 프레임을 추가(push)하고 메소드가 종료되면 해당 프레임을 제거(pop)한다.
  • 예외 발생 시에 printStackTrace() 메소드는 이 스택 영역을 기준으로 프레임을 출력한다.
  • 프레임 내부에 로컬 변수 스택이 존재한다.
    • 변수도 추가(push) 되고 제거(pop) 된다.
    • 변수에 최초로 값이 저장되어 초기화될 때, 추가(push)된다.
    • 변수는 선언된 블록 안에서만 스택에 존재하고, 블록을 벗어나면 스택에서 제거된다.
      • if문 블록 안에 어떤 변수가 있다면, if문이 끝나면 해당 변수는 로컬 변수 스택에서 빠져(pop)나간다.
int a = 1;

if ( a == 1 ) {
  int b = 1;
  int c = 1;
} // b와 c는 블록이 끝나면서 `pop`된다.

int d = 1;

2.4. 참조 타입 변수의 ==, != 연산

  • 기본 타입 변수의 ==, != 연산은 값이 같은지 다른지 확인한다.
  • 참조 타입 변수의 ==, != 연산읜 참조하는 주소의 값이 같은지 다른지 확인한다.
    • 내용이 같은지는 확인하지 않는다.

2.5. null과 NullPointerException

  • 참조 타입 변수가 힙 영역의 주소를 참조하지 않으면, null을 갖는다.
  • null을 갖는 참조 타입 변수도 초기화되었다고 생각하기 때문에 스택 영역에 올라간다.
  • null을 가진 참조 타입 변수를 이용하려고 하면, NullPointerException이 발생한다.

2.6. String 타입

  • String은 참조 타입 변수다.
  • 같은 리터럴을 저장하는 참조 타입 변수는 같은 힙의 주소를 참조한다.
    • 단, new String()과 같이 새로운 객체를 생성한 경우에는 다른 주소를 참조한다.
  • String 끼리의 내용을 비교할 때는 .equals() 메소드를 쓰는게 정확하다.

문자열 타입은 char와 달리 큰따옴표(")로 감싼 문자 또는 문자 열을 의미합니다.

여기서 이스케이프 문자를 사용할 수 있는데 이는 문자열 내부에 역슬래시(\)가 붙은 문자를 사용한 것

 

2.7. 배열 타입

  • 같은 타입의 많은 데이터를 다룰 때 사용한다.
  • 다른 타입을 저장하려고 하면 타입 불일치(Type mismatch) 컴파일 오류가 발생한다.
  • 한 번 생성된 배열은 길이를 늘리거나 줄일 수 없다.

2.7.1. 배열 선언 포맷

int[] array1;
int array1[];
  • 타입 옆에 대괄호([])나 변수명 옆에 대괄호([]) 어느 방식으로도 가능하다.
  • 배열 역시 참조 변수에 속하므로 null을 참조하여 초기화될 수 있다.

2.7.2. 값 목록 및 new 연산자로 배열 생성

int[] a = {1, 2, 3};
int b[] = new int[] {1, 2, 3};
int[] c = new int[] {1, 2, 3};
int d[];
d = new int[] {1, 2, 3};

위 코드 중 a의 경우가 특별한데, 배열 생성 후 즉시 초기화 할 때만 문법에서 new int[]가 생략된다고 이해하면 쉽다.

테스트

2.7.3. 배열의 타입별 초기값

  • 정수형 기본 타입
    • byte[]: 0
    • char[]: \u0000
    • short[]: 0
    • int[]: 0
    • long[]: 0L
  • 실수형 기본 타입
    • float[]: 0.0F
    • double[]: 0.0
  • 논리형 기본 타입
    • boolean[]: false
  • 참조 타입
    • 클래스[]: null
    • 인터페이스[]: null

2.7.4. 배열 길이

  • 배열변수.length

2.7.5. 다 차원 배열

int[][] scores = new int[2][3];
  • 다차원 배열은 앞의 숫자에 계속해서 뒤의 숫자만큼 자식 트리로 뻗어나간 공간이 생긴다고 생각하면 쉽다.
  • 위는 2개의 트리에 3개의 자식트리가 각각 달리니 2*3만큼의 공간이 생긴다.
  • 다차원 배열은 수학 행렬구조가 아니라 계단식 구조도 가질 수 있다.
int stair = new int[2][];
stair[0] = new int[2];
stair[1] = new int[3];
  • 위 코드에서 stair[0]에는 2개의 공간이 연결된 반면에 stair[1]에는 3개의 공간이 연결되어 있다.
    • 시각화해보면 정사각형이 아닌 계단형이다.

2.7.6. 객체를 참조하는 배열

  • 배열이 객체를 참조하면, 배열 객체가 힙 영역에 생긴다.
    • 힙 영역에 생긴 배열 객체 내부에서는 배열의 주소마다 힙 영역에 있는 다른 객체를 참조하는 형태가 된다.

2.7.7. 배열 복사

  • 배열은 한번 생성하면 크기를 변경할 수 없기 때문에, 더 큰 배열을 만들어 이전의 배열을 복사하는 일이 꽤 있다.
    • System.arraycopy() 메소드를 이용해 주로 복사한다.
  • 참조 타입의 배열을 복사하면, 참조 주소를 그대로 복사하기 때문에 참조하는 원본의 주소는 같다.
    • 위와 같은 복사를 얕은 복사(shallow copy)라 한다.
    • 참조하는 객체도 별도로 생성하는 것은 깊은 복사(deep copy)라고 한다.

2.7.8. 향상된 for 문

  • 기존의 for문 처럼 카운터 변수(i)와 증감식(i++)을 사용하지 않는 형태이다.
int[] scores = {95, 71, 84, 93, 87};

int sum = 0;

for (int score : scores) {
  sum += score;
}

2.8. 열거 타입(enummeration type)

  • 한정된 값만을 갖는 타입을 열거 타입이라 한다.
    • 열거 타입은 몇 개의 열거 상수(enumeration constant) 중에서 하나의 상수를 저장하는 데이터 타입이다.

2.8.1. 열거 타입 선언

public enum Week {
  MONDAY,
  TUESDAY,
  WEDNESDAY,
  THURSDAY,
  ...
}
  • 열거 타입의 이름은 일반적 관례상 첫 글자를 대문자로 한다.
  • 열거 타입에 들어가는 상수들은 모든 문자를 대문자로 한다.
    • 여러 단어가 들어가는 경우 언더바(_)로 구분한다.
      • ex) MONDAY_MORNING, LOGIN_SUCCESS

2.8.2. 열거 타입 변수

Week today = Week.SUNDAY;
  • 일반적인 클래스의 타입을 선언하듯 선언하고, 사용하면 된다.
  • 해당 변수는 힙 영역에 있는 열거타입 상수를 참조하게 된다.

2.8.3. 열거 타입 메소드

  • name() 메소드
    • 열거 객체가 가지고 있는 문자열을 리턴한다.
Week today = WEEK.SUNDAY;
today.name(); // "SUNDAY"
  • ordinal() 메소드
    • 열거 객체 중 몇 번째 열거 객체인지 알려준다.
Week monday = WEEK.MONDAY;
Week sunday = WEEK.SUNDAY;

monday.ordinal(); // 0, 첫번째 열거 상수
sunday.oridnal(); // 6, 마지막 열거 상수
  • compareTo() 메소드
    • 매개값으로 주어진 열거 객체를 기준으로 전후 몇번째 위치하는지를 반환한다.
Week monday = WEEK.MONDAY;
Week wednesday = WEEK.WEDNESDAY;

monday.compareTo(wednesday); // -2
wednesday.compareTo(monday); // 2
  • values() 메소드
    • 열거 타입의 모든 열거 객체들을 배열로 만들어 리턴한다.
Week[] days = Week.values();

for (Week day : days) {
  System.out.println(day); // MONDAY, TUESDAY ...
}
728x90

댓글