-
Notifications
You must be signed in to change notification settings - Fork 1
Day 09(21.09.13)
Method 영역에는 코드에서 사용되는 'Class'들을 클래스 로더로 읽어들여, field 데이터, method 데이터, method 코드, constructor 코드 등을 분류하여 저장한다.
객체와 배열이 생성되는 영역이다. Heap 영역에 생성된 객체와 배열은 Stack 영역의 변수나 다른 객체의 필드에서 참조한다.
참조하는 변수나 field가 없다면 JVM은 GC를 실행시켜 자동으로 Heap 영역에서 제거한다.
C언어 계열에서는 이런 의미 없는 객체를 삭제할때 포인터라는 걸 따로 사용해야 한다고 한다.
각 Thread 마다 하나씩 존재하며 시작될 때 할당된다.
Stack은 Method를 호출할 때마다 Frame을 추가(Push)하고, 메소드가 종료되면 해당 Frame을 제거(Pop)하는 동작을 수행한다.
프레임 내부에는 로컬 변수 Stack이 있는데, 기본 타입(int, double 등) 변수와 참조 타입 변수가 Push되거나 Pop된다.
변수의 초기 값을 저장할때(초기화) 이 영역에 변수가 생성되는데, 선언된 블록 안에서만 Stack에 존재하고 이를 벗어나면 Pop된다.
하나의 변수는 하나의 데이터만 저장할 수 있다. 이 말은, 데이터의 수가 많아지면 필연적으로 필요한 변수의 수가 증가한다는 얘기다. 예를 들어, 학생의 성적이나 사원의 근무 평가를 기록한다고 할 때, 소수 인원의 경우 학생 1, 또는 사원 1 의 변수를 따로따로 생성한뒤, 전부 개별로 관리할 수 있다. 하지만, 학교 전체 단위나 전사 차원의 관리가 필요한 경우에는 개별 인원에 대한 변수를 따로 생성하는 것은 현실적으로 무리에 가깝다. 총점이나 평균 등, 내부 데이터를 활용한 작업을 수행할 경우에는 말할 것도 없다.
이러한 작업을 효율적으로 수행할 수 있게 도와주는 것이 바로 배열이다. 배열은 같은 타입의 데이터를 연속된 공간에 나열시키고, 각 테이터에 Index를 부여해 놓은 자료구조이다. 이를 이해하기 쉽게 설명하자면,
학생 1번 : 김철수
학생 2번 : 김영희
학생 3번 : 권민수
...
위와 같이 학생 몇 번이라는 Index에 학생의 이름을 저장하는 자료구조라는 것이다.
중요한 점은 배열의 index는 1이 아니라 0 부터 시작된다.
아래는 학생 30명의 평균 점수를 출력하는 프로그램을 만든다고 가정했을 때의 코드이다.
int sum = 0;
for(int i=0; i < 30; i++ {
sum += score[i];
}
int avg = sum / 30;위 코드의 for문은 0부터 29까지 30개의 index의 data를 전부 더한 값을 sum으로 반환한다.
그렇게 반환된 sum을 30으로 나누어 평균 avg를 얻게되는데, 이렇게 하면 30명이 아니라 수 천명의 평균을 구할때도 for문의 숫자만 수정하면 되므로 엄청 효율적인 자료구조라할 수 있다.
- 배열은 같은 타입의 데이터만 저장할 수 있다.
int 배열은 int 값만 저장할 수 있고, String 배열은 String만 저장할 수 있다. 만약 다른 타입의 값을 저장하려고 하면 Type mismatch로 컴파일 에러가 발생한다.
배열의 타입은 배열이 선언됨과 동시에 결정되는데 이는 아래에서 확인할 수 있다. - 배열의 index는 0부터 시작이다.
예시에서 언급했지만 배열의 index는 1이 아닌 아래와 같이 0부터 시작된다.
data 1 2 3 4 5
index [0] [1] [2] [3] [4]
-
한 번 생성된 배열은 길이를 변경할 수 없다.
3개의 값을 저장하는 배열을 생성하면 도중에 5개의 값을 저장하는 배열로 수정할 수 없고, 그 반대도 마찬가지다.
만약 5개의 값을 저장해야할 경우, 길이 5의 새로운 배열을 생성하고 기존 항목을 새로 생성한 배열로 복사해야 한다. -
배열 변수는 참조 변수에 속한다.
배열도 객체이므로 Heap 영역에 생성되고, 배열 변수는 Heap 영억의 배열 객체를 참조하게 된다. 여기서 참조할 배열 객체가 없다면 배열 변수는 null 값으로 초기화될 수 있다.
배열을 사용하기 위해서는 배열 변수를 선언해야 한다. 두 가지 방법이 있는데,
타입[] 변수; 타입 변수[]
int[] intArray; int intArray[];
double[] doubleArray; double double[];
String[] strArray; Strubg strArray[];
위와 같이 배열을 선언할 수 있다.
배열 항목에 저장될 value의 list가 있다면 다음과 같이 간단하게 배열 객체를 만들 수 있다.
데이터타입[] 변수 = {value0, value1, value2, value3, ...
int[] scores = {83, 90, 87}
위와 같은 경우, scores라는 변수에 83, 90 , 87의 값이 저장되는 길이 3의 배열이 자동으로 생성된다.
배열이 먼저 생성되고 value list가 나중에 결정되는 상황이라면 다음의 방법을 사용하면 된다.
value list는 없지만, 나중에 value를 저장할 배열을 미리 만들고 싶다면 new 연산자를 사용해 배열 객체를 만들 수 있다.
타입[] 변수 = new 타입[길이];
int[] intArray = new int[5];
위의 경우엔 길이가 5인 배열, intArray가 생성된다. 여기서 길이란, 배열이 저장할 수 있는 값의 수를 말한다.
위에서 말했듯이 나중에 value를 저장할때 new 연산자를 사용해 배열을 생성하는데, 이때 배열의 value는 0으로 초기화된다.
이렇게 생성된 배열에 value를 저장하려면 대입 연산자를 사용하면된다.
변수[index] = value;
intArray[0] = 1;
위의 경우엔 생성해둔 intArray의 0번 인덱스, 즉 첫번째 위치에 1이라는 value를 저장한다는 뜻이 된다.
배열의 길이란 배열에 저장할 수 있는 항목 수를 말한다. 코드에서 배열의 길이를 얻으려면 배열 객체의 length field를 읽으면 된다.
배열의 length field를 읽으려면 배열 변수에 '.' 연산자를 붙이고 length를 적어주면 된다.
int[] intArray = {10, 20, 30};
int num = intArray.length;
System.out.println(num);
// intArray.length = 10; → 에러 발생위와 같이 사용할 수 있는데 이때, length field는 읽기 전용이기 때문에 값을 바꿀 수가 없다. 때문에 위 에러 발생 행과 같이 작성하면 에러가 발생한다.
아래는 학생 5명의 영어 점수와 국어 점수를 배열로 활용할 때의 예시이다.
public class Score {
public static void main(String[] args) {
//학생 5명으로 영어 점수의 값을 모를때
int[] engScore = new int [5];
//engScore 배열의 각 index에 value 저장
engScore[0] = 100;
engScore[1] = 90;
engScore[2] = 80;
engScore[3] = 70;
engScore[4] = 60;
//학생 5명의 국어 시험 점수의 값을 알고 있을때
//배열의 선언과 동시에 koreanScore 배열의 각 index를 초기화할 수 있다.
int[] koreanScore = {80, 70, 60, 50, 40};
//세번째 학생의 영어 점수는?
System.out.println(engScore[2]);
//국어 점수의 총합은?
int krTotal = 0;
for (int i = 0; i < koreanScore.length; i++) {
krTotal += koreanScore[i];
}
System.out.printf("국어 점수의 총합은 %d점", krTotal);
}
}값들이 행과 열로 구성된 배열을 2차원 배열이라고 한다. 고등학교에서 배우는 행렬을 생각하면 된다.
이 경우에는 가로 index와 세로 index를 사용하는데, 자바에서는 중첩 배열 방식으로 구현한다. 예를 들면 다음과 같다.
int[][] scores = new int [2][3] // 2행 3열 구조의 2차원 배열 생성이 코드는 메모리 영역 중에서도 heap 영역(배열은 참조 변수이므로)에 배열 객체가 세 개 생성된다. 편의상 A, B, C라고 부르겠다.
배열 변수인 scores는 먼저 length가 2인 배열 A를 먼저 참조하는데, 여기서 scores[0]은 다시 length가 3인 배열 B를 참조한다. 그리고 scores[1] 또한 length가 3인 배열 C를 참조하는 방식으로 다차원 배열이 작동하게 된다.
다차원 배열 또한 배열과 마찬가지로 value list를 가지고 있냐 없냐에 따라 다양하게 생성할 수 있는데, value list가 있을때도
타입[][] 변수 = { {value0a, value0b, value0c ...}, {value1a, value1b, value1c} };위와 같이 생성할 수 있다. 사용 예시는 아래와 같다.
int[][] scores = { {95, 80}, {92, 96} };
//위 scores 배열에서 항목값 불러오기
int score = scores[0][0]; //출력 값: 95
int score = scores[1][1]; //출력 값: 96위 예시를 통해 scores 배열은
0열 1열
0행 95 80
1행 92 96
이와 같은 2*2 형태의 배열로 생성되었다는 것을 알 수 있다.