------- 1편 포스팅에 이어서
다차원 배열)
행과 열로서 구성되 배열을 2차원 배열이라고 한다. 행과 열로 구성되어 있기 때문에 가로 인덱스와 세로인덱스를 사용한다.
자바는 2차원 배열을 중첩 배열 방식으로 구현하기위해 다음과 같은 코드를 사용한다.
ex. 2행 3열의 배열) int[ ][ ] first = new int[2][3] |
이 코드는 메모리에 3가지 배열 객체를 생성한다.
스택에 참조되는 1번째 배열 객체는 ① 부분을 생각하면 된다. 행의 수만큼 길이의 배열이 생성되며 각 인덱스에 각 행에 대한 배열 객체의 주소(=번지)를 갖는다.
그리고 그렇게 연결된 각 객체들은 동일한 길이 또는 각각 다른 길이의 배열을 갖고 각 인덱스마다 값을 갖는다..
배열의 길이는 다음 처럼 볼 수 있다.
int[][] first = {{1,2,3},{4,5,6}};
System.out.println(first.length); // 2 행의 수
System.out.println(first[0].length); // 3 인덱스 0번의 열의 수
System.out.println(first[1].length); // 3 인덱스 1번의 열의 수
그럼 2번째 행의 3번째 값을 알고 싶다면 어떻게 해야할까
2번째 행은 인덱스 1번에 위치하고, 3번째는 인덱스 2번에 위치한다
따라서
first[1][2] 이렇게 순서대로 넣어 값인 6을 읽을 수 있다.
비유 ? (조금더 잘 정리해야할 거 같다)
![](https://blog.kakaocdn.net/dn/u388y/btrQZPVk0IV/Dlpgb3YpVZhkmN31MMmbA0/img.png)
학생이름을 정리할 목적의 1학년이라는 이름의 다차원 배열이 있다고 하자. (반이름은 임의로 붙인것)
1학년이라는 변수가 처음으로 참조하는 배열 객체 길이는 반의 개수(행의 수)만큼이고 각 칸에 반의 이름(객체주소)이 적혀있다. ①
첫번째 칸의 반 이름을 따라 A반에 가보면 A반 이름이 번호 순서대로 배열되어 있다. ②
두번째 칸의 반 이름을 따라 B반에 가보면 B반 이름이 번호 순서대로 배열되어 있다. ③
A반과 B반 인원수가 다른것도 가능하다.
이 1학년 배열에 대해 length를 물어보게 되면
1학년.length는 2라고 대답할 것이다. A반, B반 2개가 존재하기 때문
그러면 1학년[0].length를 물으면 3이라고 대답할 것이다. 1학년 배열 0번에는 A반이 연결되어 있고 A반에 1,2,3 3명이 존재하기 때문
1학년[1].length를 물어도 3이라고 대답할 거다. 다만 이번엔 B반과 연결되어 있고 B반에 4,5,6 3명이 존재하기 때문에 3명이라 답하는 거다.
그럼 B반의 3번째 친구 이름을 알고 싶다면 어떻게 해야할까
B반은 반들 중 인덱스 1번에 위치하고, B반 인원수 중 3번째는 인덱스 2번에 위치한다
따라서
first[1][2] 이렇게 순서대로 넣어 값인 6을 읽을 수 있다.
다차원 배열은 다음과 같이 3가지 방법으로 선언할 수 있으며 반복문에서는 아래같이 사용 가능하다.
int[][] mathScores = new int[2][3]; // 행과 열 선언
int[][] englishScores = new int[2]; // 행 수만 먼저 선언
englishScores[0] = new int[2]; // 열 선언
englishScores[1] = new int[3];
int[][] javaScores = {{95, 80},{92, 96, 80}} // 값과 함께 선언
// 아래처럼 사용가능
for(int i=0; i<javaScores.length; i++){
for(int k=0; k<javaScores[i].length; k++){
System.out.println("javaScores[" + i + "][" + k + "]=" + javaScores[i][k]);
}
}
객체를 참조하는 배열)
기본 타입의 배열은 각 항목의 직접 값을 가지고 있지만, 참조타입 배열은 항목에 객체의 번지를 가지고 있다.
배열에 넣었다 하더라도 비교하는 방식이 바뀌는 건 아닌것이다. 따라서 == 연산자가 동일한 값이 아닌 동일한 객체인지 판별하는 연산인 것도 동일하며 String[] 배열도 각각 String 객체의 번지 값을 가지고 있기 때문에 문자열 비교를 위해 기존 String클래스가 하는 방법처럼 equals() 메소드를 사용해야 한다.
배열 복사)
배열은 한번 생성하면 크기를 변경할 수 없기 때문에 더 많이 저장하려면 더 큰 배열을 만들고 배열 값을 복사해 넣어줘야 한다.
1. for문으로 복사
int[] oldIntArray = {1, 2, 3};
int[] newIntArray = new int[5];
for(int i=0; i<oldIntArray.length; i++){
newIntArray[i] = oldIntArray[i];
}
for(int i=0; i< newIntArray.length; i++){
System.out.println(newIntArray[i]);
}
// 1, 2, 3, 0, 0
값이 넘어가지 않은 나머지 부분은 초기값으로 유지된다.
2. System.arraycopy() 메소드로 복사
int[] oldIntArray = {1, 2, 3};
int[] newIntArray = new int[5];
System.arraycopy(oldIntArray, 0, newIntArray, 0, oldIntArray.length);
for(int i=0; i< newIntArray.length; i++){
System.out.println(newIntArray[i]);
}
// 1, 2, 3, 0, 0
System.arraycopy( | oldIntArray, | 0, | newIntArray, | 0, | oldIntArray.length | ); |
원본 배열 | 복사할 시작 인덱스 |
새로운 배열 | 복사 받을 시작 인덱스 |
복사할 개수 |
for-each문)
자바는 배열이나 컬렉션을 좀 더 쉽게 처리하기 위해 향상된 for문을 제공한다.
int[] scores = {95, 71, 84, 93, 87};
int sum = 0;
for(int score : scores){
sum += score;
}
System.out.println("점수총합 : "+sum);
double avg = (double) sum/ scores.length;
System.out.println("점수평균 : "+avg);
for ( | int score | : | scores | ) { ③ 실행문 } |
① 배열에서 가져오는 값이 대입될 변수 | : | ② 대상 배열 |
for-each문 실행 흐름은
1. for문 실행시 ②대상배열에서 가져올 값이 있는 지 판단한다.
2. 값이 존재하면 그 값을 ①변수에 대입한다. (값이 없다면 종료한다.)
3. ③실행문을 실행한다.
4. ③실행문이 모두 실행됬다면 다시 1번으로 돌아간다.
Chapter 05-2 확인문제
4. for문을 이용해서 주어진 배열의 항목에서 최대값을 구해보세요.
int max = 0;
int[] array = {1, 5, 3, 8, 2};
// 작성위치
System.out.println(max);
int max = 0;
int[] array = {1, 5, 3, 8, 2};
for(int i : array){
if(i > max){
max = i;
}
}
System.out.println(max);
5. 중첩 for문을 이용해서 주어진 배열의 전체 항목의 합과 평균값을 구해보세요.
int[][] array = {
{95, 86},
{83, 92, 96},
{78, 83, 93, 87, 88}
};
int sum = 0;
double avg = 0.0;
// 작성위치
System.out.println("sum : "+sum);
System.out.println("avg : "+avg);
int[][] array = {
{95, 86},
{83, 92, 96},
{78, 83, 93, 87, 88}
};
int sum = 0;
double avg = 0.0;
int count = 0;
for(int i=0; i< array.length; i++){
for(int k=0; k <array[i].length; k++){
sum += array [i][k];
count++;
}
}
avg = (double) sum / count;
System.out.println("sum : "+sum);
System.out.println("avg : "+avg);
// sum : 881
// avg : 88.1
6. 키보드로 부터 학생 수와 각 학생들의 점수를 입력받아서, 최고 접수 및 평균 점수를 구하는 프로그램입니다. 실행 결과를 보고 알맞게 작성해보세요.
public static void main(String[] args) {
boolean run = true;
int studentNum = 0;
int[] scores = null;
Scanner scanner = new Scanner(System.in);
while(run){
System.out.println("--------------------------------------------------------");
System.out.println("1.학생수 | 2.점수입력 | 3. 점수리스트 | 4. 분석 | 5. 종료");
System.out.println("--------------------------------------------------------");
System.out.println("선택>");
int selectNo = Integer.parseInt(scanner.nextLine());
if(selectNo == 1){
//작성위치
} else if (selectNo == 2){
//작성위치
} else if (selectNo == 3){
//작성위치
} else if (selectNo == 4){
//작성위치
} else if (selectNo == 5) {
run = false;
}
}
System.out.println("프로그램 종료");
}
--------------------------------------------------------
//1.학생수 | 2.점수입력 | 3. 점수리스트 | 4. 분석 | 5. 종료
//--------------------------------------------------------
//선택>
//1
//학생수>
//3
//--------------------------------------------------------
//1.학생수 | 2.점수입력 | 3. 점수리스트 | 4. 분석 | 5. 종료
//--------------------------------------------------------
//선택>
//2
//score[0]>
//88
//score[1]>
//95
//score[2]>
//79
//--------------------------------------------------------
//1.학생수 | 2.점수입력 | 3. 점수리스트 | 4. 분석 | 5. 종료
//--------------------------------------------------------
//선택>
//3
//score[0]>88
//score[1]>95
//score[2]>79
//--------------------------------------------------------
//1.학생수 | 2.점수입력 | 3. 점수리스트 | 4. 분석 | 5. 종료
//--------------------------------------------------------
//선택>
//4
//최고 점수 : 95
//평균 점수 : 87.33333333333333
//--------------------------------------------------------
//1.학생수 | 2.점수입력 | 3. 점수리스트 | 4. 분석 | 5. 종료
//--------------------------------------------------------
//선택>
//5
//프로그램 종료
public static void main(String[] args) {
boolean run = true;
int studentNum = 0;
int[] scores = null;
Scanner scanner = new Scanner(System.in);
while(run){
System.out.println("--------------------------------------------------------");
System.out.println("1.학생수 | 2.점수입력 | 3. 점수리스트 | 4. 분석 | 5. 종료");
System.out.println("--------------------------------------------------------");
System.out.println("선택>");
int selectNo = Integer.parseInt(scanner.nextLine());
if(selectNo == 1){
System.out.println("학생수>");
studentNum = Integer.parseInt(scanner.nextLine());
} else if (selectNo == 2){
scores = new int[studentNum];
for(int i=0; i<scores.length; i++){
System.out.println("score["+i+"]>");
scores[i] = Integer.parseInt(scanner.nextLine());
}
} else if (selectNo == 3){
for(int i=0; i<scores.length; i++){
System.out.println("score["+i+"]>" + scores[i]);
}
} else if (selectNo == 4){
int max = 0;
int sum = 0;
for(int i=0; i<scores.length; i++){
sum += scores[i];
if(scores[i]>max){
max = scores[i];
}
}
double avg = (double) sum / scores.length;
System.out.println("최고 점수 : " + max);
System.out.println("평균 점수 : " + avg);
} else if (selectNo == 5) {
run = false;
}
}
System.out.println("프로그램 종료");
}
05-3 / 열거타입
열거타입은 한정된 값인 열거 상수(enumeration constant) 중에서 하나의 상수를 저장하는 타입이다.
열거타입 선언)
열거 타입을 선언하기 위해서는 먼저 열거 타입의 이름을 정하고 해당 이름으로 소스파일(.java)를 생성해야 한다.
열거 타입 이름은 관례적으로 첫글자는 대문자 나머지로 소문자 구성하며 여러단어일 경우 각 단어 첫글자는 대문자로 하는 것이 관례.
ex. MemberGrade.java , ProductKind.java
열거타입 선언 키워드는 public enum으로 반드시 소문자로 작성해야한다. 그리고 열거 타입 이름은 소스파일 이름과 대소문자가 모두 일치해야 한다.
그리고 열거 상수는 모두 대문자로 작성하는 것이 관례다.
열거 타입 변수)
열거 타입을 선언했다면 , 열거 타입 변수를 선언하는 방법은 아래와 같다
Week now; // 열거 타입 변수 선언
Week today = Week.Sunday; // 열거 상수 저장
Week birthday = null; // 열거타입도 참조타입이다.
열거 상수 또한 객체로 생성되기 때문에 열거 타입 또한 참조 타입 변수이다.
열거 상수 7개로 선언한 Week 변수는 Monday부터 Sunday까지 총 7개의 객체를 생성하게 된다. 그리고 메소드 영역에 생성된 열거 상수가 해당 Week 객체를 각각 참조하게 된다.
Week today = Week.Sunday;
열거타입 변수는 today는 스택 영역에서 생성된다. today에 저장되는 값은 Week.SUNDAY 열거 상수가 참조하는 객체의 번지를 복사한 값이다. 따라서 열거 상수 Week.SUNDAY와 today변수는 서로 같은 Week 객체를 참조하게 된다. 그래서 둘을 == 연산 하게 되면 true 결과가 나온다.
열거 타입 Week를 이용해 보려면 날짜 정보가 필요하다.
자바는 Calendar 클래스를 통해 컴퓨터의 날짜, 요일, 시간을 제공한다.
import java.util.Calendar;
public class chap01 {
public static void main(String[] args) {
Calendar now = Calendar.getInstance();
int year = now.get(Calendar.YEAR);
int month = now.get(Calendar.MONTH);
int day = now.get(Calendar.DAY_OF_MONTH);
int week = now.get(Calendar.WEEK_OF_MONTH);
int hour = now.get(Calendar.HOUR);
int minute = now.get(Calendar.MINUTE);
int second = now.get(Calendar.SECOND);
}
}
이를 통해 오늘 요일을 얻는 예시
import java.util.Calendar;
public class chap01 {
public static void main(String[] args) {
Week today = null;
Calendar now = Calendar.getInstance();
int week = now.get(Calendar.DAY_OF_WEEK);
switch(week){
case 1:
today = Week.SUNDAY; break;
case 2:
today = Week.MONDAY; break;
case 3:
today = Week.TUESDAY; break;
case 4:
today = Week.WEDNESDAY; break;
case 5:
today = Week.THURSDAY; break;
case 6:
today = Week.FRIDAY; break;
case 7:
today = Week.SATURDAY; break;
}
System.out.println("오늘 요일 : "+today);
if(today == Week.SUNDAY){
System.out.println("일요일에는 휴식을 취합니다");
} else {
System.out.println("열심히 자바 공부를 합니다.");
}
}
}
// 오늘 요일 : SATURDAY
// 열심히 자바 공부를 합니다.
+질문 |
* 열거상수 객체가 생성되는 시점. 열거타입 변수를 생성할때? 아니면 빌드 되면서 메소드 영역에 열거상수 저장될 때? - 열거 타입도 static 타입이기 때문에 변수 선언시 생성되는 게 아니라 빌드 될때 생성된다. * 만약 열거타입 변수가 참조를 끊더라도 열거 상수 같은 경우는 메소드 영역에서 참조되고 있으므로 가비지 콜렉터가 제거하는 대상에서 제외되나? - 가비지 콜렉터는 Heap영역에서만 활동한다. 메소드영역이나 스택영역에서는 가비지 콜렉터가 활동하지 않으므로 열거타입은 대상이 되지않는다. |
'Programming > Java' 카테고리의 다른 글
혼공자바] 06-2 필드 (0) | 2022.11.23 |
---|---|
혼공자바] 06-1 객체 지향 프로그래밍 (0) | 2022.11.22 |
혼공자바] 05-1~2 참조 타입과 참조 변수 (1) (0) | 2022.11.11 |
혼공자바] 04-1 조건문과 반복문 (0) | 2022.11.10 |
혼공자바] 03 연산자 (0) | 2022.11.08 |