숫자나 문자열을 담을 수 있는 변수를 배웠다.
많은 데이터의 평균을 구한다던지, 프로그램이 커질수록 많은 변수를 사용해야 한다.
이제 배울 배열은, 변수를 보다 편리하게 사용하기 위한 방법이다.
배열을 사용함으로써 한번에 많은 변수를 처리할 수 있다.
배열의 최초의 요소는 0번이다.
1. 기본적인 배열
int[] arr = new int[3]; // [3]이 부분이 길이가 됨 arr[0] = 3; arr[1] = 4; arr[2] = 5;
가장 기본적이고 많이 쓴다.
2. 정해진 숫자가 있을 때.
int[] arr = {3, 4, 5};
선언과 정의를 분리할 수 없다.
안에 들어갈 원소들을 다 알고 있어야 한다.
그래서 실제로 그렇게 많이 쓰이진 않는다.
- 이름과 같이 쓸 때, 파라미터안에 넣을 때.
int[] arr = new int[] {3, 4, 5};
public class Main {
public static void main(String[] args) {
int[] score; // 배열변수의 선언
score = new int[5]; // 요소의 작성과 대입
} // 5개짜리 상자를 만드는 것이라고 생각!
}
public class Main {
public static void main(String[] args) {
int[] score = new int[5];
}
}
public class Main {
public static void main(String[] args) {
int[] score = new int[5];
int count = score.length;
System.out.println("요소의 수 " + count);
}
}
❗️ int count = score.length;
배열로 만든 것은 length라고 하는 내부적인 값이 있는데,
그 값을 통해 길이를 얻을 수 있다.
public class Main {
public static void main(String[] args) {
int[] score;
score = new int[5];
score[1] = 30; // 두 번째 요소에 30 대입
System.out.println(score[1]);
}
}
❗️ score[1] = 30;
[] 이 부분에 들어갈 숫자는 0 ~ 4까지이다.
당연히 5를 넣으면 에러가 난다.
원래는 초기화 하지 않고 정수를 넣게 되면 에러가 난다.
public class Main {
public static void main(String[] args) {
int x;
System.out.println(x); // 컴파일 에러
}
}
변수를 사용하기 전에는 반드시 초기화를 해야 한다.
기존에 우리가 정수를 사용할 때,
선언을 하고 값을 넣지 않은 상황에서 println을 사용하게 되면 컴파일 에러가 난다.
하지만! 배열은 다르다.
public class Main {
public static void main(String[] args) {
// 배열의 요소는 자동으로 초기화된다.
// 5개의 요소가 전부 0으로 초기화
int score = new int[5];
System.out.println(score[0]); // 에러아님!
}
}
배열은 일반 int랑 다르게 5개짜리 공간을 확보하게 되면
저절로 0이 전부다 들어가 있다고 판단한다.
따라서 에러가 나지 않는다.
int[] score1 = new int[] {20, 30, 40, 50, 80};
int[] score2 = {20, 30, 40, 50, 80}; // 이 식이 일반적.
범위를 벗어난 요소를 이용할 때 예외(exception)가 발생한다.
예외: 에러
score[1] = 30; // 두 번째 값에 30 대입.
위에서 봤듯이,
[] 이 부분에 들어갈 숫자는 0 ~ 4까지이다.
당연히 5를 넣으면 에러가 난다.java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds ...
그냥 일반적으로 한 식
public class Normal {
public static void main(String[] args) {
int math = 20;
int korean = 30;
int science = 40;
int english = 50;
int society = 80;
int sum = math + korean + english + society;
int avg = sum / 5;
System.out.println("합계: " + sum);
System.out.println("평균: " + avg);
}
}
배열을 이용한 식
public class Test3 {
public static void main(String[] args) {
int[] score = {20, 30, 40, 50, 80};
int sum = score[0] + score[1] + score[2] + score[3] + score[4];
int avg = sum / score.length;
System.out.println("합계: " + sum);
System.out.println("평균: " + avg);
}
}
❗️ int sum = score[0] + score[1] + score[2] + score[3] + score[4];
0부터 하는 거 조심 ! 1부터 시작 아님 !!
❗️ int avg = sum / score.length;
length는 배열의 개수를 알려준다.
/ 5대신 length를 활용함으로써 숫자를 건드리지 않고 고정시킬 수 있다.
처음에 비해 코드가 많이 좋아졌다.
좀 더 개선해보자.
과목이 늘어났을 때에 합계를 구할 때 수정 할 부분들이 있다.
for문과 조합하여 해결할 수 있다.
public class Test3 {
public static void main(String[] args) {
int[] score = {20, 30, 40, 50, 80};
for (int i = 0; i < score.length; i++) {
System.out.println(score[i]);
}
}
} // 20 ~ 80까지 출력.
int[] score = {20, 30, 40, 50, 80};
// 일반 for문
for (int i = 0; i < score.length; i++) {
System.out.println(score[i]);
}
// 향상된 for문(for each문)
for (int value : score) {
System.out.println(value);
}
}
}
❗️ for-each문
: for (int value : score) {...}
원래 for문은 앞에 인덱스를 다루는 변수를 활용하는데,
for each문은 실제 값을 넣는 변수를 사용한다.
score안에 있는 숫자를 하나하나 갖고오면서 반복한다.
컴퓨터 내부에 변수가 할당된 모습.
- int는 4바이트를 저장하니까 한칸이 메모리인 1바이트라고 봤을 때,
차지하는 a가 메모리에 차지하게 된다.- 왼쪽의 숫자는 주소인데, 메모리안에는 주소가 있다.
- 몇 번째 몇 번째 주소가 있는데, 실제로 이 값은 아니고 막 써놓은 것이다.
- a는 맨앞에 있는 주소(빨간색)를 두고 컴퓨터가 값을 찾으러 다닐 수 있다.
배열 변수에는 5개의 요소가 들어있는 것이 아니다.
최초의 요소의 주소(address 또는 reference)가 대입된다.
❗️int[] score = new int[5];를 실행했을 때의 메모리상의 모습
1. int형 요소를 5개 가지는 배열(파란색)이 메모리상에 작성 됨.
2. int[]형의 배열변수 score(주황색)가 메모리상에 작성됨.
3. score에 배열의 선두요소의 주소가 대입 됨.
배열처럼 변수명을 지정 했을 때, 그 값이 아니라 주소를 가리키는 것을 참조(reference)라고 한다.
그리고 그 변수를 참조형(reference type) 변수라고 한다.
int 나 boolean 같은 "기본형(primitive type)"변수와 구별된다.
public class Test4 {
public static void main(String[] args) {
int[] a = {1, 2, 3};
int[] b;
b = a; // 1, 2, 3
b[0] = 100; // 100, 2, 3
System.out.println(a[0]);
} // 결과값: 100
}
- 이것을 이해하기 위해서는 메모리의 원리를 이해해야 한다.
- a가 {1,2,3} 들어있고, b는 a이 값이 아니라, a의 주소를 저장한다.
그래서 a와 b는 같은 주소로 저장되어 있다.- 그 주소는 각각 1,2,3이 저장된 곳을 나타낸다.
- 그래서 b의 첫 번째 값에 100을 넣었을 때,
똑같이 a의 첫 번째 값에 100이 들어간다.
둘 다 배열의 첫 번째 값을 보고 있는 것이다.
"참조형" 변수는 "기본형" 과는 다르다고 했다.
배열의 경우도 마찬가지로 조금 다른 점들을 살펴 보자.
public class Main {
public static void main(String[] args) {
boolean b = true;
if (b == true) {
int[] i = {1, 2, 3}; //new가 생략되어 있는 것.
}
}
}
int[] i = {1, 2, 3};
new가 생략되어 있으므로, 블록이 끝나도 수명을 다하지 않고 살아있다.
이러한 것이 메모리 내의 쓰레기가 되는 것.
new로 확보된 요소들은 보통의 변수와 다르기 때문에,
블록이 끝나도 수명이 다하지 않는다.
블록 내에서 생성된 배열은 이 후 어떤 방법으로도 읽거나 쓸 수 없고 메모리를 차지하고 있다. 사실상 메모리 내의 쓰레기(gerbage)가 된다.
원래 이렇게 사용하지 않게 된 메모리는 프로그래머가 정리를 하여야 한다.
하지만 Java는 가비지 컬렉션 (GC, garbage collection)이라는 장치가 더 이상 사용되지 않는 메모리를 정리 해 준다.
public class Test4 {
public static void main(String[] args) {
int[] a = {1, 2, 3};
a = null;
a[0] = 10;
} // 결과값: 에러(NullPointerException)
}
a는 1, 2, 3을 보고 있다가 여기서 null를 넣게 됨으로써, 이제 값을 보지 않게됨. 그래서 a에 10을 넣게 되더라도 아무것도 보지 못하게 되는 것.
- String의 length()는 한글, 영문, 공백 관계없이 1문자로 카운트
- 배열의 length와 비슷하지만 ()를 붙여야 한다.
public class Main {
public static void main(String[] args) {
String s = "Java로 개발";
System.out.println(s.length());
}
}
3행 3열
2행 3열 Code
public class Test4 {
public static void main(String[] args) {
int[][] scores = new int[2][3]; //2행 3열
scores[0][0] = 40;
scores[0][1] = 50;
scores[0][2] = 60;
scores[1][0] = 80;
scores[1][1] = 60;
scores[1][2] = 70;
System.out.println(scores[1][1]);
} // 결과값: 60
}
public class Test4 {
public static void main(String[] args) {
int[][] scores = { {10, 20, 30}, {30, 40, 50} };
System.out.println(scores.length);
System.out.println(scores[0].length);
} // 결과값: 2
// 3
}
연관된 글
: Java 배열 정렬