희렌버핏
5장 참조 타입 본문
5.1 데이터 타입 분류
1. 기본 타입
- 값을 갖는 타입
- 직접 스택 영역에 값을 저장함
2. 참조 타입
- 객체를 참조
- 객체의 번지를 가짐
- 스택에는 번지수를 저장, 힙 영역에 주소를 갖고 있는 객체가 값을 저장
5.2 메모리 사용 영역
- 프로그램을 실행하게 되면 JVM(자바 가상 머신)을 구동하게 되는데, JVM을 구동할 때 OS로부터 할당받은 세개의 메모리 영역(Runtime Data Area)이 있다.
① 메소드 영역
- 생성 시점 : JVM을 시작할 때
- 저장 되는 것 : 로딩된 클래스 바이트 코드 내용을 분석 후 저장
- 공유 범위 : 모든 스레드
② 힙 영역
- 생성 시점 : JVM을 시작할 때
- 저장 되는 것 : 객체/배열
- 사용하지 않는 객체는 GC(가비지 콜렉터, 쓰레기 수집기)가 자동으로 제거
③ JVM 스택
- 스레드별로 생성
- 메소드를 호출할 때마다 Frame을 스택에 추가(push)
- 메소드를 종료하면 Frame을 제거(pop)
- Frame 안에 변수들이 생성된다.
*** 실시간으로 메모리가 사용되는 흐름
ㄱ. java MemoryExample : 자바를 실행시킬 때 java.exe 라는 JVM 구동 명령어를 사용해서 MemoryExample이라는 class를 실행시켜준다.
ㄴ. JVM 구동됨 : 운영체제에서 받은 메모리 영역(Runtime Data Area)이 생성되면서 '메소드 영역'과 '힙 영역'이 자동적으로 생성된다.
ㄷ. MemoryExample 로딩 : MemoryExample 클래스를 메모리에 로딩 (바이트 코드를 로딩), 메소드 영역에 클래스에 대한 내용이 올라가게 된다, 메소드의 '코드'라던지 '필드 내용'이라던지 이런것들이 올라감. 코드 자체가 올라가는 것이 아니라 분석된 것이 올라감.
ㄹ. main 스레드 생성 (main 메소드를 실행시키는 코드 흐름) : main 스레드가 생성됨과 동시에 'JVM 스택'이 생성된다.
ㅁ. main 메소드 호출 : JVM 스택에 프레임(main 메소드를 호출하는)이 하나 생성됨.
ㅂ. main 메소드 실행
public static void main(String[] args){ // String 배열이 매개변수 값으로 들어온다.
}
- 프레임 영역 안에 100번지 주소를 가진 'args' 변수가 생성
- 힙 영역에 String 배열 객체가 생성됨.
ㅅ.
public static void main(String[] args){
int sum = 0;
}
- 'args'와 같은 프레임 안에 'sum' 변수가 생성되고, 객체 없이, 주소 없이 '0'이라는 값이 들어감
ㅇ.
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);
}
public static int add(int a, int b){
return a + b;
}
- 'v2'도 같은 프레임에 생성되고 직접 '10' 값이 저장된다.
- 'v3'도 같은 프레임에 생성되고 직접 '20' 값이 저장된다.
- 'add' 메소드에 대한 새로운 프레임이 생성됨
- 'v2'와 'v3'는 'a'와 'b' 변수에 대입됨
- add가 return 값을 sum에 저장하게 해줌
- add 메소드가 끝나게 되면 JVM 스택에 쌓였던 add 메소드 프레임이 삭제된다.
- return한 '30' 값이 'sum'에 삽입된다
- if문이 끝나면 if문 안에 선언됐던 'v2'와 'v3'는 프레임 안에서 제거된다.
- 출력문을 통해 sum이 출력되고
- main에 선언됐던 'sum' 변수가 프레임 안에서 제거된다.
- 마지막으로 'args'가 제거된다.
ㅈ. JVM 종료 : Runtime Data Area도 사라진다.
*** Stack 영역에 메모리 소멸 생성 절차
5.3 참조 변수의 ==, != 연산
- 변수의 값이 같은지 다른지 비교하기 위해 비교 연산자 사용
① 기본 타입 : 변수의 값을 비교
② 참조 타입 : 변수의 주소값을 비교 (같은 객체를 참조하고 있는지)
5.4 null과 NullPointerException
*** Null
- 참조 타입의 변수에만 저장할 수 있다.
- 변수가 참조하는 객체가 없을 경우 초기값으로 사용 가능
- null이 들어가면 주소가 없기때문에 변수가 스택영역에서 'null' 값을 가지게 된다.
- ==, != 비교 연산 가능
*** NullPointerException
- 예외의 한 종류 (사용자의 잘못된 조작, 개발자의 잘못된 코딩으로 발생하는 오류)
- 참조 변수가 null 값을 가지고 있을 때, 객체의 필드나 메소드를 사용하려고 했을 때 발생
5.5 String 타입
- 문자열을 저장하는 클래스 타입
- 문자열 리터럴이 동일하면 String 객체를 공유
- new 연산자를 사용하면 힙영역에 새로운 String 객체를 생성.
- 주소 상관없이 문자열을 비교 : nam1.equals(name3)
5.6 배열 타입
*** 배열이란
- 같은 타입의 데이터를 연속된 공간에 저장하는 자료구조
- 각 데이터 저장 위치는 인덱스를 부여해서 접근할 수 있다.
- 항목접근 : 배열이름[인덱스]
*** 배열의 필요성
- 중복된 변수 선언을 줄이기 위해 사용
- 반복문을 이용해서 요소들을 쉽게 처리하기 위해
*** 배열 선언
- 배열 변수를 선언해야 한다.
=> 타입[ ] 변수; 타입 변수[ ];
*** 배열 변수는 참조변수이기 때문에 null로 초기화 할 수 있다.
- 타입[ ] 변수 = null;
- 배열이 null 값을 가질 때, "변수[인덱스]" 못함 (NullPointerException 발생)
5.6.3 값 목록으로 배열 생성
- 변수 선언과 동시에 값들 대입 : String[] names = {"신용권", "홍길동", "감자바"};
- 변수 선언 후 값들 대입 : String[ ] names = null;
names = new String[ ] {"신용권", "홍길동", "감자바"}; (객체를 새롭게 생성해줘야함)
=> 메소드의 매개변수로 배열을 사용할 때, 배열을 직접 생성해서 매개값을 줄 경우
int add(int[] scores) {...} //매게변수로 배열을 미리 선언하고 부여했을 경우
int result = add(new int[] {95, 85, 90}); //값 목록만 작성하면 안되고 새롭게 객체를 부여해야 한다.
5.6.4 new 연산자로 배열 생성
- int[] intArray = new int[5]; (값을 넣지 않고 길이를 지정해줌)
- 길이만 지정했을 때 초기값이 부여된다.
5.6.5 배열 길이
- 배열에 저장할 수 있는 전체 항목 수
- 배열 길이 코드 : 변수.length;
5.6.6 커맨드 라인 입력
- main 메소드에 매개변수인 'String[] args'는 값이 없는 배열객체다.
5.6.7 다차원 배열
- 2차원 배열 이상, 행렬과 같은 구조
- 길이로 다차원 배열 생성 : int[][] scores = new int[2][3];
- 값을 다차원 배열에 생성 : int[][] scores = {{95,80},{92,96}};
5.6.8 객체를 참조하는 배열
- 기본 타입 : 직접 값을 가지고 있다.
- 참조 타입 : 객체의 번지를 가지고 있다. (문자열 리터럴리 동일할 경우, 같은 주소를 갖게 된다.)
5.6.9 배열 복사
- 배열은 한번 생성하면 크기 변경 불가능
- 더 큰 공간이 필요할 경우, 더 큰 배열 만들고 작은 배열들의 값 복사
- 배열 복사 방법
- for문 이용
- System.arrayCopy(Object src, int srcPos, Object dest, int destPos, int length);
이전 배열/이전 배열 복사위치/새로운 배열/새로운 배열 붙여넣을 위치/몇개 복사할 것이냐
- Arrays 클래스 이용 방법 (기본 API 클래스에서 설명)
5.6.10 향상된 for문
for( ②타입 변수 : ①배열){
sum = sum + score;
}
int[] scores = {95,71,84,93,87};
int sum = 0;
for(int score:scores){
sum = sum + score;
}
5.7 열거 타입
- 한정된 값만을 갖는 데이터 타입 (ex. 요일, 계절)
- 열거 타입 선언
- 열거 타입 소스 파일 생성 : ~.java (열거 타입 첫문자는 대문자가 관례)
- 소스 작성 방법
- 소스 선언 : 파일 이름과 동일한 이름으로 선언 (ex. public enum 열거타입이름 {...})
- 열거 상수 정의 : 모두 대문자로, 다른 단어 결합되면 '_'로 연결
5.7.2 열거 타입 변수
- 열거 타입 변수 선언
- Week today;
- 열거 상수값 저장
- Week today = Week.SUNDAY; (열거 상수를 열거 타입 변수에 저장)
- 열거 타입 변수는 참조 타입
- null 값 저장 가능
- 열거 상수는 열거 객체를 참조한다.
- 열거 객체는 힙에 생성된다.
- 열거 상수는 메소드 영역에서 열거 객체를 참조한다.
5.7.3 열거 객체의 메소드
- 열거 객체는 열거 상수의 문자열을 내부 데이터로 가지고 있다.
- 열거 타입은 컴파일시, java.lang.Enum 클래스를 자동 상속하여 클래스가 가지고 있는 메소드를 사용할 수 있다.
'Java > 이것이 자바다' 카테고리의 다른 글
1장 자바 시작하기 (0) | 2019.02.06 |
---|