Home 5. data type advance, memory area, operator for reference variable, NullPointException, String type, Array Type
Post
Cancel

5. data type advance, memory area, operator for reference variable, NullPointException, String type, Array Type

목차

5.1 데이터 타입 분류
5.2 메모리 사용 영역
- 메모리 사용 영역 실행 순서
→ 1) JVM 구동 명령
→ 2) JVM 구동
→ 3) MemoryExample(class)을 메모리에 로딩: 바이트 코드를 로딩
→ 4) main 스레드 생성: main 메서드를 실행시키는 코드 흐름
→ 5) main() 메서드 호출
→ 6) main()의 매개변수가 String 배열 값으로 들어옴
→ 7) int sum = 0; 생성
→ 8, 9) if 문 검증 후, int v2 = 10; 생성
→ 10) add() 메소드 호출
→ 11) 프레임 제거: 값이 return 되고 모든 실행이 끝나는 시점에서 add() 메서드에 의해 생성된 프레임이 제거됨
→ 12) main() 프레임의 sum 값 변화
→ 13) main() 프레임의 v2, v3 값 제거
→ 14) 프로그램 종료
→ 15) JVM이 종료되면서 프로그램도 종료, Runtime Data Area도 없어짐
- 더 알아보기
5.3 참조 변수의 ==, != 연산
5.4 null과 NullPointerException
5.5 String 타입
5.6 배열 타입(1)
5.6 배열 타입(2)
5.6 배열 타입(3)
5.7 열거 타입
참고자료

5.1 데이터 타입 분류

Untitled

  • 기본타입: 직접 값을 가지고 있음
  • 참조타입: 객체를 참조하는 타입, 직접 값을 가지지 않고, 참조 객체의 번지를 가지고 있음
  • int age = 25, double price = 100.5 에서 25, 100.5는 기본 타입으로, 직접 값이 스택 영역에 저장됨
  • String name = “신용권”, “독서”는 힙 영역에 값을 저장한 객체가 생성되고, 이 번지가 스택 영역 변수에 저장됨 → 메모리 주소(번지)를 가지고 있다가, 필요할 주소로 때 객체를 이용

5.2 메모리 사용 영역

Untitled

  • 프로그램을 실행하면, JVM이 구동됨 → JVM이 구동될 때, OS에서 할당받은 메모리 영역을 3가지로 구분
  • 오른쪽 그림 전체가 Runtime Data Area 메모리 영역(자바가 실행될 때, 운영체제에서 받는 메모리 영역)
  • 메소드 영역: 클래스 코드들이 올라감
  • 힙 영역: 프로그램이 실행될 때, 이 객체를 이용해 데이터를 저장하거나, 메소드를 호출
  • JVM 스택:
    • 메서드를 호출할 때마다 프레임이 생성, 프레임 안에는 변수들이 위치
    • 프레임이 제거되는 시점: 프레임이 생성된 메서드 호출이 끝나게 되면 자동적으로 없어짐

메모리 사용 영역 실행 순서

1) JVM 구동 명령

1
java (exe) MemoryExample

2) JVM 구동

→ OS(운영체제)로부터 메모리를 할당받음(운영체제에서 받은 메모리 영역: Runtime Data Area)

→ Runtime Data Area 영역이 만들어지며 메소드 영역, 힙 영역 자동 생성

Untitled

3) MemoryExample(class)을 메모리에 로딩: 바이트 코드를 로딩

→ 바이트 코드가 로딩되면, 메소드 영역에 클래스 내용이 올라감

⇒ 메소드 코드, 빌드 내용 등

⇒ 코드 자체가 올라가는 것이 아닌, 분석된 내용이 올라감

1
2
3
4
5
// 메소드 영역
Class - MemoryExample.java
[메소드 코드]
public static void main(String[] args) {...}
public static void add(int a, int b) {...}

Untitled

4) main 스레드 생성: main 메서드를 실행시키는 코드 흐름

→ main 스레드 생성 동시에 JVM 스택 생성됨

Untitled

5) main() 메서드 호출

→ JVM 스택에 main 메서드 호출하는 프레임 생성됨

Untitled

6) main()의 매개변수가 String 배열 값으로 들어옴

1
2
3
public static void main(String[] args) {
  // ....
}

→ 매개변수 args가 프레임 내부에 생성됨

⇒ 프레임 - main() 내부

| 100 | args | | — | — |

⇒ 힙(Heap Area)

| String[] 배열 (100번지) | | — |

→ String 배열 객체는 heap 내부에 생성됨

⇒ 만약, 100번지에 String 배열 객체가 생성되었다면, args에는 100번지라는 주소값이 저장됨

Untitled

7) int sum = 0; 생성

1
2
3
public static void main(String[] args) {
  int sum = 0;
}

→ int sum = 0; 코드에 의해 메모리가 변형이 되는데, 변수기 때문에 프레임 내부에 생성이 됨

→ 즉, sum이라는 변수가 생성이 되며 0이라는 값이 저장됨

⇒ 프레임 - main() 내부

0 sum
100 args

Untitled

8, 9) if 문 검증 후, int v2 = 10; 생성

1
2
3
4
5
6
7
public static void main(String[] args) {
  int sum = 0;
  if (sum==0) {
    int v2 = 10;
    int v3 = 20;
  }
}

→ sum==0이면, int v2 = 10, int v3 = 20; 가 생성됨

⇒ 프레임 - main() 내부

20 v3
10 v2
0 sum
100 args

Untitled

10) add() 메소드 호출

1
2
3
4
5
6
7
8
9
10
11
12
public static void main(String[] args) {
  int sum = 0;
  if (sum==0) {
	int v2 = 10;
	int v3 = 20;
	sum = add(v2, v3);
  }
}

public static int add(int a, int b) {
  return a + b;
}

→ 메소드를 호출했기 때문에 add() 프레임이 추가됨

→ add()의 파라미터 v2, v3는 add() 메서드의 a, b에 대입이 되게 됨

→ 메모리에 a, b 변수와 각각 10, 20 값이 저장됨

⇒ 프레임 - add()

20 b
10 a

⇒ 프레임 - main()

20 v3
10 v2
0 sum
100 args

Untitled

11) 프레임 제거: 값이 return 되고 모든 실행이 끝나는 시점에서 add() 메서드에 의해 생성된 프레임이 제거됨

1
2
3
4
5
6
7
8
9
10
11
12
public static void main(String[] args) {
  int sum = 0;
  if (sum==0) {
    int v2 = 10;
    int v3 = 20;
    sum = add(v2, v3);
  }
}

public static int add(int a, int b) {
  return a + b;
} //-------(메소드 끝나는 시점)

Untitled

12) main() 프레임의 sum 값 변화

→ add() 메서드가 리턴한 값 30이 sum에 저장이 되며, main() 프레임의 sum의 값이 30으로 변함

⇒ 프레임 - main()

20 v3
10 v2
30 sum
100 args

Untitled

13) main() 프레임의 v2, v3 값 제거

→ if 문이 끝나는 시점에서 v2, v3는 메모리에서 제거됨

⇒ 프레임 - main()

30 sum
100 args
1
2
3
4
5
6
7
8
public static void main(String[] args) {
  int sum = 0;
  if (sum==0) {
    int v2 = 10;
    int v3 = 20;
    sum = add(v2, v3);
  } //----(if 끝나는 시점)
}

Untitled

14) 프로그램 종료

→ System.out.println(sum)으로 sum 의 값 출력 후

1
2
3
4
5
6
7
8
9
public static void main(String[] args) {
  int sum = 0;
  if (sum==0) {
    int v2 = 10;
    int v3 = 20;
    sum = add(v2, v3);
  }
  System.out.println(sum);
} //-----(main 메서드 끝나는 시점)

⇒ main() 메서드 종료 시점에서

⇒ int sum = 0; 으로 선언했던 변수 메모리에서 삭제됨

⇒ 매개변수인 String[] args도 삭제됨

Untitled

⇒ main()이 끝나게 되면 main() 프레임이 사라짐

Untitled

15) JVM이 종료되면서 프로그램도 종료, Runtime Data Area도 없어짐

Untitled

더 알아보기

전체

전체

기본 타입 변수

기본 타입 변수

  1. 스택에 v1라는 변수가 생성이 되며, A에 유니코드가 저장됨
  2. 스택 영역에 v2가 생성, 100 값 저장, v3 이하동일

    if 가 끝나는 시점에서 v2, v3 변수 제거됨

  3. 스택에 v4 변수 생성, true 값 저장
    • 기본 타입 변수는 직접 값을 가지고 있음

참조 타입 변수 - 배열

참조 타입 변수 - 배열

  • 10, 20, 30 값을 가진 배열 객체를 scores 변수가 “참조한다”고 해석
  • scores 변수는 스택 영역에 생성, 배열 값은 힙 영역에 생성
  • 힙 영역에 생성된 배열 객체의 번지를 스택의 scores에 저장
  • 번지 참조 변수: 배열 타입 변수는 직접 값을 가지는 것이 아닌, 배열 객체가 생성된 번지를 가짐

참조 타입 변수 - 문자열

참조 타입 변수 - 문자열

  • 위 String은 클래스 타입이며, 참조 변수
  • 객체 생성 연산자인 new를 이용해 String 객체 생성
  • name 변수는 String 객체의 번지를 가지고 있음
  • 힙 영역에 생성된, 문자열을 가진 String 객체의 번지수를 스택 영역의 name 변수에 저장
  • 힙 영역에 생성된 String 객체의 번지가 100이라면, 스택 영역의 name에는 100을 저장함
  • new 연산자를 사용하지 않고 문자열 리터럴을 사용해서 아래와 같이 생성했을 때도, 힙 영역에 해당 문자열에 대한 객체가 생성되고, 그 객체의 번지가 스택 영역의 변수에 저장됨

    1
    
      String name3 = "name";
    

5.3 참조 변수의 ==, != 연산

Untitled

  • refVar1 == refVar2: 변수에 들어있는 번지가 같은가? 서로 참조하는 객체가 서로 같은 객체인가? ⇒ false
  • ==: 같은 객체를 참조하는가?
  • ≠: 다른 객체를 참조하는가?

5.4 null과 NullPointerException

Untitled

  • 참조 타입만 null 값을 가질 수 있음
  • null도 값이기 때문에 초기화되면 스택 영역에 생성됨

Untitled

  • intArray가 null인 상태에서, 즉, 배열이 없는 상태에서 10을 저장할 수 없음
  • 참조 변수 null 값인 상태에서 데이터를 저장하려고 하거나, 객체가 가지고 있는 메서드를 호출하려고 했을 때 발생
  • str이 참조하는 문자열 객체가 없기 때문에(str = null이기 때문에) NullPointException 발생

5.5 String 타입

Untitled

  • heap 영역의 객체 번지가 stack 영역의 변수에 저장
  • new 연산자를 사용해 객체를 생성하면 무조건 새로운 객체가 생성됨

Untitled

  • ==는 stack에 저장된 객체의 번지수를 비교하기 때문에, 같은 문자열이라도 name1 == name3은 false가 나옴 → equals()로 문자열 동일 여부 비교

5.6 배열 타입(1)

Untitled

Untitled

  • 참조 변수는 직접 값을 저장하는 것이 아니라 힙 영역의 번지를 저장함 ⇒ 힙 영역의 번지가 참조되지 않을 경우에는 null값을 변수에 대입할 수 있음

Untitled

Untitled

  • 배열을 생성하고, 나중에 값을 대입하는 경우
  • 길이: 배열이 저장할 수 있는 값의 수
  • 타입이 int니까 배열의 각 칸에 4바이트씩 할당됨

Untitled

  • 배열 타입 변수의 칸 수를 정해서 생성하면, 기본값으로 각 초기값이 들어있음
  • 예시) new int[30] 이면 배열 30칸에 각 0씩, boolean[10] 이면 배열 10칸에 각 false가 기본적으로 들어가 있음

5.6 배열 타입(2)

Untitled

  • 배열의 length는 읽기 전용이며, 배열이 생성될 때 정해지기 때문에 다른 값을 대입할 수 없음
  • length는 배열의 final 필드이며, 따라서 수정할 수 없음

Untitled

1
$ java [클래스명] 
  • 위 명령어 실행 시, JVM이 구동되며 main() 메서드를 찾아 실행함.
    • JVM은 String[] 배열 객체를 만듬
    • 초기에는 값이 없으니, String[] args = {}; 형태로 (String[] args)에 파라미터로 대입됨
    • 즉, 초기에는 값이 없는 배열 객체가 대입됨

Untitled

1
$ java [클래스명] [문자열1] [문자열2] 
  • 위 명령어 실행 시, [문자열1] [문자열2] [..]형태의 배열이 String[] args 객체에 대입됨(인덱스 번호는 차례로 0, 1, 2…)
    • 이 문자열 형태의 배열이 main() 메서드 호출 시 전달됨
    • main() 메서드를 통해 args에 입력된 문자열을 얻을 수 있음
    1
    2
    3
    4
    5
    6
    
      public static void main(String[] args) {
        args[0]
        args[1]
        args.length
        // ....
      }
    

명령어 args의 length 출력하기

Untitled

  • window - show view - navigator로 위치 알아내기

Untitled

  • 커맨드 화면에서 바이트 코드 파일을 실행

Untitled

1
2
$ java [패키지이름].[클래스이름]
// 클래스 내용에 작성된 것처럼 배열의 길이가 출력됨

Untitled

Untitled

1
2
$ java [패키지이름].[클래스이름] abc def
// 배열의 길이: 2

명령 프롬프터가 아닌 이클립스에서 args 내용 출력하기

Untitled

  • Main Class: main() 메서드가 있는 클래스

Untitled

  • arguments 탭에 화면과 같이 작성하고 run

Untitled

  • abc def를 입력했으므로 배열의 길이: 2

💡 정리: args는 사용자가 실행할 때 입력한 문자 배열

다차원 배열

Untitled

  • 행, 열 모두 인덱스가 있음(행렬)
  • 자바에서는 행렬 구조로 메모리에 다차원 공간을 만들지 않음 ⇒ 1차원 배열을 이용해 2차원 배열 구현
1
2
3
int[][] scores = new int[행의 ][열의 ]

int[][] scores = new int[2][3] // 2행 3열

Untitled

  • new int[2][3]의 2로 먼저 길이 2짜리 1차원 배열 A를 만듦

    Untitled

    • 0번째 항목 값으로 길이 3짜리 1차원 배열B를 만듦
    • 1번째 항목 값으로 길이 3짜리 1차원 배열C를 만듦
  • scores[0][0] = 3; 이면, B의 0번째에 3이 저장됨
  • SCORES[1][2] = 5; 이면, C의 2번째에 5이 저장됨

Untitled

  • 1번째 배열만 정하고 나머지는 나중에 대입해도 됨
1
2
3
int[][] scores = new int[2][];
scores[0] = new int[2]; // A 배열의 0번째에 길이 2짜리 B 대입
scores[1] = new int[3]; // A 배열의 1번째에 길이 3짜리 C 대입
  • scores[0][2] = 3; 로 3을 대입했을 때, scores[0][2]에 해당하는 객체가 없기 때문에 예외 발생

5.6 배열 타입(3)

Untitled

Untitled

  • 기본 타입 배열은 각 항목에 직접 값을 가지고 있음

    Untitled

    • 스택 변수 → 힙 배열 객체 [0번째값][1번째값][2번째값][…]
    1
    2
    3
    4
    
      int[] scores = new int[3];
      scores[0] = 10;
      scores[1] = 20;
      scores[2] = 30;
    
    • 스택 변수 scores → 힙 값 {10, 20, 30} : 스택 변수가 힙 값 참조
  • 참조 타입 배열은 각 항목에 객체의 번지를 가짐

    예시 1

    예시 1

    예시2

    예시2

    예시 2의 String 객체 주소

    예시 2의 String 객체 주소

    • 스택 변수 → 힙 객체 → 힙 String 객체 : 스택 변수가 힙 객체 참조 + 힙 객체가 String 객체 잠조

Untitled

  • 이미 생성된 배열은 크기 변경 불가 ⇒ 새 배열 생성 후 값 복사

Untitled

  • System.arrayCopy(이전 배열, 이전 배열의 복사 위치, 새로운 배열, 새로운 배열의 붙여넣기 위치, 배열 복사 개수)

Untitled

  • 1) 배열의 0인덱스를 2) 변수에 대입 후 3) 실행문 실행

    → 1) 배열의 1인덱스를 2) 변수에 대입 후 3) 실행문 실행

    → 1) 배열의 2인덱스를 2) 변수에 대입 후 3) 실행문 실행

    → (반복 후) 인덱스가 끝나면 → 종료

5.7 열거 타입

Untitled

  • 한정된 값: 요일, 계절, 로그인 실패/성공 여부 등
  • 한정된 값의 하나하나가 열거 상수로 정의됨

Untitled

Untitled

  • 열거 타입을 선언하고, 열거 타입의 바이트 코드를 메모리 상에 로드하게 되면, 열거 상수는 열거 객체를 참조함
  • 열거 객체: 열거 타입을 객체화시킨 것
  • 열거 객체는 힙 영역에 생성됨
  • 열거 타입 클래스를 로딩해서 메모리로 올림 → 메서드 영역에 바이트 코드가 저장됨 → 열거 상수는 메소드 영역에 저장됨 → 메서드 영역에 자리잡은 열거 상수는 힙 영역의 열거 객체를 참조함
  • 힙 영역의 Week 열거 객체는 열거 상수와 동일한 문자열을 가지고 있음
  • 예시1) 메소드 영역에 저장된 MONDAY 열거 상수 → 힙 영역의 Week 객체 중 MONDAY 문자열이 저장된 열거 객체를 참조함
  • 예시2) 메소드 영역에 저장된 SUNDAY 열거 상수 → 힙 영역의 Week 객체 중SUNDAY 문자열이 저장된 열거 객체를 참조함
  • 총 7개의 열거 상수가 총 7개의 열거 객체를 각각 참조하게 됨

Untitled

  • 메소드 영역에 만들어진 열거 상수가 힙 영역의 열거 객체의 번지 값을 저장하고, 스택의 변수가 힙 영역의 열거 객체의 번지 값을 저장함

Untitled

Untitled

  • name(): 열거 객체의 문자열 리턴
  • ordinal(): 열거 객체의 순번 리턴(제일 위에 선언된 열거 객체부터 0번)
  • compareTo(): 열거 객체의 순번 차이
  • valueOf(String name): 주어진 문자열의 열거 객체를 리턴
    • valueOf(MONDAY): MONDAY를 문자열로 가지고 있는 열거 객체의 번지 리턴
    1
    
      Week weekDay = Week.valueOf("SATURDAY");
    
    • SUNDAY 문자열을 가진 열거 객체의 생성 번지를 weekDay에 대입
    • weekDay가 참조하는 열거 객체는 열거 상수 SUNDAY가 참조하는 열거 객체와 동일
  • values(): 모든 열거 객체들을 배열로 리턴
    • 총 7개의 열거 상수가 정의되어 있다면, 총 7개의 열거 객체가 만들어 지므로, 7개의 열거 객체를 열거 타입 배열로 담아 리턴

    Untitled

    1
    2
    3
    4
    
      Week[] days = Week.values();
      for(Week day:days) {
        System.out.println(day);
      }
    
    • Week.values()로 열거 객체 배열 생성 → 배열의 생성 번지 100을 Week[] days 변수에 대입 → days 변수가 index로 각 열거 객체에 접근
    • 힙 영역의 100번지에 만들어진 객체의 각 index에는 열거 객체가 저장됨

참고자료

강의교안_5장.ppt

This post is licensed under CC BY 4.0 by the author.
Contents