제7장 배열(Arrays) 배열(Arrays) • 배열은 대량의 정보를 조직화하는데 도움이 되는 객체 • 7장 내용 배열 선언과 사용 경계 검사 및 용량 객체 참조를 저장하는 배열 가변 길이 매개변수 리스트 다차원 배열 ArrayList 클래스 다각형과 다선분 마우스 이벤트와 키보드 이벤트 © 2004 Pearson Addison-Wesley. All rights reserved 7-2 목차 배열 선언과 사용 객체들의 배열 가변 길이 매개변수 리스트 이차원 배열 ArrayList 클래스 다각형(Polygon) 및 다선분(Polyline) 마우스 이벤트와 키 이벤트 © 2004 Pearson Addison-Wesley. All rights reserved 7-3 배열 • 배열은 값들의 리스트인데, 이 리스트에는 순서 개념이 있다. 각 값에는 숫자 인덱스가 부여된다 전체 배열에 단일 이름이 주어진다 0 scores 1 2 3 4 5 6 7 8 9 79 87 94 82 67 98 87 81 74 91 크기가 N인 배열의 인덱스는 0에서 N-1까지이다. 위의 배열은 10개의 값을 가지며, 인덱스는 0에서 9까지이다. © 2004 Pearson Addison-Wesley. All rights reserved 7-4 배열 • 배열 원소 배열 이름 다음에 대괄호 안의 인덱스를 사용한다. 예를 들면 scores[2] 위의 표현은 정수 한 개를 저장할 장소를 나타내며 정수 변수가 사용될 수 있는 곳이면 어디서나 사용될 수 있다. © 2004 Pearson Addison-Wesley. All rights reserved 7-5 배열 • 배열 원소의 사용 값의 배정 계산에 사용 값의 프린트 scores[2] = 89; scores[first] = scores[first] + 2; mean = (scores[0] + scores[1])/2; System.out.println ("Top = " + scores[5]); © 2004 Pearson Addison-Wesley. All rights reserved 7-6 배열 • 배열 원소(array element) 배열에 저장된 값들 배열은 원소 타입(element type)의 여러 값들을 저장한다. 원소 타입은 기초 타입일 수도 있고 객체 참조일 수도 있다. • 예 정수 배열, 문자 배열, String 객체 배열, Coin 객체 배열 등 • 배열 자체도 하나의 객체이며, 따라서 반드시 실체화되어야 한다. © 2004 Pearson Addison-Wesley. All rights reserved 7-7 배열 • 앞의 scores 배열을 객체 개념을 반영하여 아래 그림과 같이 나타낼 수도 있다: scores © 2004 Pearson Addison-Wesley. All rights reserved 79 87 94 82 67 98 87 81 74 91 7-8 배열 선언(Declaring Arrays) • scores 배열 선언 int[] scores = new int[10]; • 변수 scores의 타입은 int[], 즉 정수 배열이다. • 배열 타입 자체는 크기를 지정하지 않으며, 배열 타입 객체가 특정 크기를 갖는다는 점을 유의하라. • 참조 변수 scores는 10개의 정수를 저장할 수 있는 새로운 배열 객체로 설정된다. © 2004 Pearson Addison-Wesley. All rights reserved 7-9 배열 선언 • 배열 선언의 보기: float[] prices = new float[500]; boolean[] flags; flags = new boolean[20]; char[] codes = new char[1750]; © 2004 Pearson Addison-Wesley. All rights reserved 7-10 배열의 사용 • 배열 원소 처리에 반복자(iterator)를 사용하는 for 루프를 이용할 수 있다. for (int score : scores) System.out.println (score); • 배열 내의 모든 원소를 처음부터 끝까지 처리할 때 가장 적절하다. • BasicArray.java 참조 (372쪽) © 2004 Pearson Addison-Wesley. All rights reserved 7-11 BasicArray.java // 기본적인 배열 선언과 사용을 보여준다. public class BasicArray { public static void main (String[] args) { final int LIMIT = 15, MULTIPLE = 10; int[] list = new int[LIMIT]; // 배열 값 초기화 for (int index = 0; index < LIMIT; index++) list[index] = index * MULTIPLE; list[5] = 999; // 하나의 배열 값 변경 } // 배열 값 프린트 for (int value : list) System.out.print (value + " "); © 2004 Pearson Addison-Wesley. All rights reserved } 7-12 BasicArray.java 실행 결과 0 10 20 30 40 999 60 70 80 90 100 110 120 130 140 © 2004 Pearson Addison-Wesley. All rights reserved 7-13 경계 검사 (Bounds Checking) • 일단 배열이 생성되면 크기가 고정된다. • 배열 참조 인덱스 값은 0에서 N-1 범위 안에 있어야 한다. 배열 인덱스가 유효 범위를 벗어나면, Java 인터프리터는 ArrayIndexOutOfBoundsException 발생 • 경계 검사 이러한 자동 인덱스 검사 메커니즘 © 2004 Pearson Addison-Wesley. All rights reserved 7-14 경계 검사 예 • 배열 codes가 100개의 값을 저장할 수 있다면, 인덱스 범위는 0에서 99까지이다. • 예외상황 발생 count = 100; System.out.println (codes[count]); • 1-차이 오류(off-by-one error)가 흔히 나타난다. 틀린 부분 for (int index=0; index <= 100; index++) codes[index] = index*50 + epsilon; © 2004 Pearson Addison-Wesley. All rights reserved 7-15 경계 검사 • 배열 크기 각 배열은 크기를 나타내는 공용 상수 length 제공 scores.length length는 최대 인덱스가 아니라 원소 개수를 나타낸다. • ReverseOrder.java 참조 (374쪽) • LetterCount.java 참조 (375쪽) © 2004 Pearson Addison-Wesley. All rights reserved 7-16 ReverseOrder.java (1/2) // 배열 인덱스 처리 과정을 보여준다. import java.util.Scanner; public class ReverseOrder { //------------------------------------------------------// 사용자로부터 정수들을 입력받아 배열에 저장하고 // 역순으로 프린트한다. //------------------------------------------------------- © 2004 Pearson Addison-Wesley. All rights reserved 7-17 ReverseOrder.java (2/2) public static void main (String[] args) { double[] numbers = new double[10]; System.out.println("The size of the array: " + numbers.length); for (int index = 0; index < numbers.length; index++) { System.out.print ("Enter number " + (index+1) + ": "); numbers[index] = Keyboard.readDouble(); } System.out.println ("The numbers in reverse order:"); } } for (int index = numbers.length-1; index >= 0; index--) System.out.print (numbers[index] + " "); © 2004 Pearson Addison-Wesley. All rights reserved 7-18 ReverseOrder.java 실행 결과 The size of the array: 10 Enter number 1: 18.36 Enter number 2: 48.9 Enter number 3: 53.5 Enter number 4: 29.06 Enter number 5: 72.404 Enter number 6: 34.8 Enter number 7: 63.41 Enter number 8: 45.55 Enter number 9: 69.0 Enter number 10: 99.18 The numbers in reverse order: 99.18 69.0 45.55 63.41 34.8 72.404 29.06 53.5 48.9 1 8.36 © 2004 Pearson Addison-Wesley. All rights reserved 7-19 LetterCount.java (1/3) // 배열과 스트링사이의 관계를 보여준다. import java.util.Scanner; public class LetterCount { // 사용자로부터 문장을 읽어 들이고 // 그 안에 포함된 대문자와 소문자 수를 센다. public static void main (String[] args) { final int NUMCHARS = 26; Scanner scan = Scanner.create(System.in); int[] upper = new int[NUMCHARS]; int[] lower = new int[NUMCHARS]; © 2004 Pearson Addison-Wesley. All rights reserved 7-20 LetterCount.java (2/3) char current; // 현재 처리되고 있는 문자 int other = 0; // 알파벳이 아닌 문자를 세는 카운터 System.out.println ("Enter a sentence:"); String line = scan.nextLine.(); // 각 문자가 발생하는 수를 센다. for (int ch = 0; ch < line.length(); ch++) { current = line.charAt(ch); if (current >= 'A' && current <= 'Z') upper[current-'A']++; else if (current >= 'a' && current <= 'z') lower[current-'a']++; else other++; } © 2004 Pearson Addison-Wesley. All rights reserved 7-21 LetterCount.java (3/3) // 결과 프린트 System.out.println (); for (int letter=0; letter < upper.length; letter++) { System.out.print ( (char) (letter + 'A') ); System.out.print (": " + upper[letter]); System.out.print ("\t\t" + (char) (letter + 'a') ); System.out.println (": " + lower[letter]); } } } System.out.println (); System.out.println ("Non-alphabetic characters: " + other); © 2004 Pearson Addison-Wesley. All rights reserved 7-22 LetterCount.java 실행 결과 Enter a sentence: In casablanca, Humphrey Borgart never says “Play it again, Sam.” A: 0 a: 10 B: 1 b: 1 C: 1 c: 1 D: 0 d: 0 …………………………. Z: 0 z: 0 Non-alphabetic characters: 14 © 2004 Pearson Addison-Wesley. All rights reserved 7-23 다른 배열 구문 • 배열 타입 표시에 사용되는 대괄호는 원소 타입에 연계될 수도 있고 배열 이름에 연계될 수도 있다. • 따라서 아래 두 선언은 동등한 효과를 갖는다: float[] prices; float prices[]; • 일반적으로 첫 번째 형식이 읽기 쉬우며, 가급적 이 형식을 사용해야 한다. © 2004 Pearson Addison-Wesley. All rights reserved 7-24 초기화 리스트 (Initializer List) • 배열 초기화 리스트 중괄호로 묶고 콤마로 분리한다. 배열 크기를 지정하지 않는다. 배열 크기는 초기화 리스트 안의 값의 개수에 의해 정해진다. 초기화 리스트는 배열 선언 시에만 사용될 수 있다. new 연산자를 사용하지 않는다 • 보기: int[] units = {147, 323, 89, 933, 540, 269, 97, 114, 298, 476}; char[] letterGrades = {'A', 'B', 'C', 'D', ’F'}; © 2004 Pearson Addison-Wesley. All rights reserved 7-25 Primes.java // 배열을 위한 초기화 리스트 사용를 보인다. public class Primes { // 배열 안의 소수 값을 저장하고 프린트한다. public static void main (String[] args) { int[] primes = {2, 3, 5, 7, 11, 13, 17, 19}; System.out.println ("Array length: " + primes.length); System.out.println ("The first few prime numbers are:"); for (int prime = 0; prime < primes.length; prime++) System.out.print (primes[prime] + " "); } } System.out.println (); © 2004 Pearson Addison-Wesley. All rights reserved 7-26 Primes.java 실행 결과 Array length: 8 The first few prime numbers are: 2 3 5 7 11 13 17 19 © 2004 Pearson Addison-Wesley. All rights reserved 7-27 배열 매개변수 • 배열 전체를 메쏘드에 매개변수로 전달할 수 있다. 다른 객체의 경우와 마찬가지로 배열 참조가 전달되며, 형식 매개변수와 실 매개변수가 서로에 대한 별명(alias)이 된다. 해당 메쏘드 안에서 배열 원소를 변경하면 원 배열도 변경된다. • 개별 배열 원소를 메쏘드에 매개변수로 전달할 수 있다. 이 경우 형식 매개변수의 타입은 배열 원소 타입과 동일하다. © 2004 Pearson Addison-Wesley. All rights reserved 7-28 목차 배열 선언과 사용 객체들의 배열 가변 길이 매개변수 리스트 이차원 배열 ArrayList 클래스 다각형(Polygon) 및 다선분(Polyline) 마우스 이벤트와 키 이벤트 © 2004 Pearson Addison-Wesley. All rights reserved 7-29 객체들의 배열 (Arrays of Objects) • 배열 원소가 객체 참조인 배열 예: 5개의 String 객체 참조를 저장하는 배열 String[] words = new String[5]; 위의 선언으로 String 객체 자체가 생성되는 것은 아니다. • 객체 배열의 초기값은 null 참조들로 채워진다. • 배열 안의 각 객체는 개별적으로 실체화되어야 한다. © 2004 Pearson Addison-Wesley. All rights reserved 7-30 객체들의 배열 • 처음 선언되었을 때의 words 배열의 모습: words - • 이 시점에서 아래와 같은 참조는 NullPointerException을 발생시킬 것이다. System.out.println (words[0]); © 2004 Pearson Addison-Wesley. All rights reserved 7-31 객체들의 배열 • 몇 개의 String 객체들이 생성되어 배열에 저장된 후의 모습: “friendship” words “loyalty” “honor” - © 2004 Pearson Addison-Wesley. All rights reserved 7-32 객체들의 배열 초기화 • 객체들의 배열 초기화 가능 String 객체들의 경우는 리터럴을 사용하여 초기화 가능하다. • 예 String[] verbs = {"play", "work", "eat", "sleep"}; “play” verbs “work” “eat” “sleep” - © 2004 Pearson Addison-Wesley. All rights reserved 7-33 객체들의 배열 • 아래 예제는 Grade 객체들로 이루어지는 배열을 생성한다. 각 Grade 객체는 스트링 표현과 최소 점수 값을 갖는다. • GradeRange.java 참조 (382쪽) • Grade.java 참조 (384 쪽) • 그리고 CD 객체들의 모음을 관리하는 예제를 살펴보자. • Tunes.java 참조 (385 쪽) • CDCollection.java 참조 (386 쪽) • CD.java 참조 (389쪽) © 2004 Pearson Addison-Wesley. All rights reserved 7-34 GradeRange.java // 객체들의 배열 사용을 보인다. public class GradeRange { // 가능한 학점과 각 학점의 최저 점수를 저장하고 프린트한다. public static void main (String[] args) { Grade[] grades = { new Grade("A", 95), new Grade("A-", 90), new Grade("B+", 87), new Grade("B", 85), new Grade("B-", 80), new Grade("C+", 77), new Grade("C", 75), new Grade("C-", 70), new Grade("D+", 67), new Grade("D", 65), new Grade("D-", 60), new Grade("F", 0) }; } for (Grade letterGrade : grades) System.out.println (letterGrade); }© 2004 Pearson Addison-Wesley. All rights reserved 7-35 GradeRange.java 실행 결과 A AB+ B BC+ C CD+ D DF 95 90 87 85 80 77 75 70 67 65 60 0 © 2004 Pearson Addison-Wesley. All rights reserved 7-36 Grade.java (1/2) // 학점을 나타낸다. public class Grade { private String name; private int lowerBound; // 구성자: Grade 객체를 명시된 학점 이름과 그 최저 점수로 설정한다. public Grade (String grade, int cutoff) { name = grade; lowerBound = cutoff; } // 이 학점의 스트링 표현을 반환한다. public String toString() { return name + "\t" + lowerBound; } © 2004 Pearson Addison-Wesley. All rights reserved 7-37 Grade.java (2/2) // 이름 설정 메쏘드. public void setName (String grade) { name = grade; } // 최저 점수 설정 메쏘드. public void setLowerBound (int cutoff) { lowerBound = cutoff; } // 이름 접근 메쏘드. public String getName() { return name; } } // 최저 점수 접근 메쏘드. public int getLowerBound() { return lowerBound; } © 2004 Pearson Addison-Wesley. All rights reserved 7-38 Tunes.java // 객체 배열의 사용을 보이기 위한 드라이버 public class Tunes { // CDCollection 객체 생성, CD 추가, 현재 상태를 프린트 public static void main (String[] args) { CDCollection music = new CDCollection (); music.addCD music.addCD music.addCD music.addCD ("Storm Front", "Billy Joel", 14.95, 10); ("Come On Over", "Shania Twain", 14.95, 16); ("Soundtrack", "Les Miserables", 17.95, 33); ("Graceland", "Paul Simon", 13.90, 11); System.out.println (music); music.addCD ("Double Live", "Garth Brooks", 19.99, 26); music.addCD ("Greatest Hits", "Jimmy Buffet", 15.95, 13); } System.out.println (music); }© 2004 Pearson Addison-Wesley. All rights reserved 7-39 Tunes.java 실행 결과 (1/2) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ My CD Collection Number of CDs: 4 Total value: $61.75 Average cost: $15.44 CD List: $14.95 $14.95 $17.95 $13.90 10 16 33 11 Storm Front Come On Over Soundtrack Graceland © 2004 Pearson Addison-Wesley. All rights reserved Billy Joel Shania Twain Les Miserables Paul Simon 7-40 Tunes.java 실행 결과 (2/2) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ My CD Collection Number of CDs: 6 Total value: $97.69 Average cost: $16.28 CD List: $14.95 $14.95 $17.95 $13.90 $19.99 $15.95 10 16 33 11 26 13 Storm Front Come On Over Soundtrack Graceland Double Live Greatest Hits © 2004 Pearson Addison-Wesley. All rights reserved Billy Joel Shania Twain Les Miserables Paul Simon Garth Brooks Jimmy Buffet 7-41 CDCollection.java (1/3) // CD 모음을 표현한다. import CD; import java.text.NumberFormat; public class CDCollection { private CD[] collection; private int count; private double totalCost; // 최초의 빈 CD 모음을 생성한다. public CDCollection () { collection = new CD[100]; count = 0; totalCost = 0.0; } © 2004 Pearson Addison-Wesley. All rights reserved 7-42 CDCollection.java (2/3) // CD 모음에 CD를 추가하고 필요하면 크기를 증가한다. public void addCD (String title, String artist, double cost, int tracks) { if (count == currentSize) increaseSize(); } collection[count] = new CD (title, artist, value, tracks); totalCost += cost; count++; // CD 모음을 나타내는 리포트를 반환한다. public String toString() { NumberFormat fmt = NumberFormat.getCurrencyInstance(); String report= "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"; report += "My CD Collection\n\n"; © 2004 Pearson Addison-Wesley. All rights reserved 7-43 CDCollection.java (3/3) report += "Number of CDs: " + count + "\n"; report += "Total value: " + fmt.format(totalCost) + "\n"; report += "Average cost: " + fmt.format(totalCost/count); report += "\n\nCD List:\n\n"; for (int cd = 0; cd < count; cd++) report += collection[cd] + "\n"; } return report; // 더 큰 배열을 생성하고 기존의 배열을 복사함으로써 // CD 모음의 크기를 두 배로 한다. private void increaseSize () { CD[] temp = new CD[collection.length * 2]; for (int cd = 0; cd < collection.length; cd++) temp[cd] = collection[cd]; } collection = temp; }© 2004 Pearson Addison-Wesley. All rights reserved 7-44 CD.java (1/2) // CD를 나타낸다. import java.text.NumberFormat; public class CD { private String title, artist; private double value; private int tracks; // 명시된 정보로 새로운 CD를 생성한다. public CD (String name, String singer, double cost, int numTracks) { title = name; artist = singer; value = cost; tracks = numTracks; } © 2004 Pearson Addison-Wesley. All rights reserved 7-45 CD.java (2/2) // CD에 대한 설명을 반환한다. public String toString() { NumberFormat fmt = NumberFormat.getCurrencyInstance(); String description; description = fmt.format(value) + "\t" + tracks + "\t"; description += title + "\t" + artist; } } return description; © 2004 Pearson Addison-Wesley. All rights reserved 7-46 Arrays of Objects • Tunes 프로그램을 위한 UML 다이어그램은 다음과 같다: Tunes CDCollection - collection : CD[] - count : int - totalCost : double + main (args : String[]) : void + addCD (title : String, artist : String, cost : double, tracks : int) : void + toString() : String - increaseSize() : void CD - title : String - artist : String - cost : double - tracks : int 1 * + toString() : String © 2004 Pearson Addison-Wesley. All rights reserved 7-47 명령-줄 인자 • 명령-줄 인자(command-line arguments) main 메쏘드의 매개변수로 String 객체들의 배열을 받는다. public static void main (String[] args) • 예 > java StateEval pennsylvania texas arizona args[0] args[1] args[2] • NameTag.java 참조 (391쪽) © 2004 Pearson Addison-Wesley. All rights reserved 7-48 NameTag.java // 명령-줄 인수 사용을 보인다. public class NameTag { //--------------------------------------------------------// 사용자가 명시하는 인사말과 이름을 이용해 간단한 이름표 출력하기 //--------------------------------------------------------public static void main (String[] args) { System.out.println (); System.out.println (" " + args[0]); System.out.println ("My name is " + args[1]); System.out.println (); } } © 2004 Pearson Addison-Wesley. All rights reserved 7-49 NameTag.java 실행 결과 >java NameTag Howdy John Howdy My name is John >java NameTag Hello William Hello My name is William © 2004 Pearson Addison-Wesley. All rights reserved 7-50 목차 배열 선언과 사용 객체들의 배열 가변 길이 매개변수 리스트 이차원 배열 ArrayList 클래스 다각형(Polygon) 및 다선분(Polyline) 마우스 이벤트와 키 이벤트 © 2004 Pearson Addison-Wesley. All rights reserved 7-51 가변 길이 매개변수 리스트 • 호출할 때마다 처리할 데이터 개수가 달라지는 메쏘드를 만든다고 생각해보자. • 예를 들어, 정수 매개변수들의 평균을 반환하는 average라는 이름의 메쏘드를 정의해보자. // 3개의 값의 평균 계산을 위한 호출 mean1 = average (42, 69, 37); // 7개의 값의 평균 계산을 위한 호출 mean2 = average (35, 43, 93, 23, 40, 21, 75); © 2004 Pearson Addison-Wesley. All rights reserved 7-52 가변 길이 매개변수 리스트 • 이와 같은 average 메쏘드를 정의하는 방법 (1) 중복정의(overloading)를 사용하는 것이다. 단점: 각 매개변수 개수에 대해 별도의 메쏘드 정의가 필요하다. (2) 정수 배열을 받아들이는 메쏘드를 정의하는 것이다. 단점: 이러한 메쏘드 호출 전에 매번 배열을 생성하고 정수 값들을 배열에 저장해야 한다. (3) 가변 길이 매개변수 리스트(variable length parameter list) © 2004 Pearson Addison-Wesley. All rights reserved 7-53 가변 길이 매개변수 리스트 • 동일 타입의 임의의 개수를 매개변수로 받는 메쏘드를 정의할 수 있다. • 호출 시, 매개변수들은 자동적으로 배열 안에 들어간다. 가변 길이 매개변수 리스트를 나타냄 public double average (int ... list) { // 아무 내용이나 } 원소 타입 배열 이름 © 2004 Pearson Addison-Wesley. All rights reserved 7-54 가변 길이 매개변수 리스트 public double average (int ... list) { double result = 0.0; if (list.length != 0) { int sum = 0; for (int num : list) sum += num; result = (double)num / list.length; } return result; } © 2004 Pearson Addison-Wesley. All rights reserved 7-55 가변 길이 매개변수 리스트 • 매개변수의 타입은 기초 타입일 수도 있고 객체 타입일 수도 있다. public void printGrades (Grade ... grades) { for (Grade letterGrade : grades) System.out.println (letterGrade); } • 가변 개수의 매개변수를 받는 매쏘드가 또 다른 매개변수들을 받을 수도 있다. public void test (int count, String name, double ... nums) { // 아무 내용이나 } © 2004 Pearson Addison-Wesley. All rights reserved 7-56 가변 길이 매개변수 리스트 • 가변 길이 매개변수는 반드시 형식 인자의 끝에 나타나야 한다. • 하나의 메쏘드에서 두 세트의 가변 길이 매개변수를 사용할 수 없다. • 구성자에서 가변 개수 매개변수를 사용할 수도 있다. • VariableParameters.java 참조 (393쪽) • Family.java 참조 (394쪽) © 2004 Pearson Addison-Wesley. All rights reserved 7-57 VariableParameters.java // 가변 길이 매개변수 리스트의 용법을 보여준다. public class VariableParameters { // 가변 개수의 String 객체를 매개변수로 받아들이는 구성자를 // 사용하여 두 개의 Family 객체를 생성한다. public static void main (String[] args) { Family lewis = new Family ("John", "Sharon", "Justin", "Kayla"); Family camden = new Family ("Stephen", "Annie", "Matt", "Mary", "Simon", "Lucy", "Ruthie", "Sam", "David"); } } System.out.println(lewis); System.out.println(); System.out.println(camden); © 2004 Pearson Addison-Wesley. All rights reserved 7-58 VariableParameters.java 실행 결과 John Sharon Justin Kayla Stephen Annie Matt Mary Simon Lucy Ruthie Sam David © 2004 Pearson Addison-Wesley. All rights reserved 7-59 Family.java // 가변 길이 매개변수 리스트의 사용을 보인다. public class Family { private String[] members; // 구성자: 이 가족을 매개변수로 전달될 // (여러 개의) 이름들을 저장함으로써 설정한다. public Family (String ... names) { members = names; } // 이 가족의 스트링 표현을 반환한다. public String toString() { String result = ""; for (String name : members) result += name + "\n"; } } return result; © 2004 Pearson Addison-Wesley. All rights reserved 7-60 목차 배열 선언과 사용 객체들의 배열 가변 길이 매개변수 리스트 이차원 배열 ArrayList 클래스 다각형(Polygon) 및 다선분(Polyline) 마우스 이벤트와 키 이벤트 © 2004 Pearson Addison-Wesley. All rights reserved 7-61 이차원 배열 • 일차원 배열(one-dimensional array) 원소 리스트를 저장한다. • 이차원 배열(two-dimensional array) 행들(rows)과 열들(columns)로 이루어진 테이블로 간주될 수 있다. 이차원 일차원 © 2004 Pearson Addison-Wesley. All rights reserved 7-62 이차원 배열 • 정확히 말하자면, Java에서 이차원 배열 “배열들로 이루어진 배열”이다. • 이차원 배열은 행과 열의 크기로 선언된다: int[][] scores = new int[12][50]; • 두 개의 인덱스 사용하여 배열 원소 참조: value = scores[3][6]; • 한 개의 인덱스를 사용하여 한 개의 행을 나타내는 배열을 가리킬 수 있다. © 2004 Pearson Addison-Wesley. All rights reserved 7-63 이차원 배열 표현 table 타입 int[][] 설명 table[5] int[] 정수 배열 table[5][12] int 정수 이차원 정수 배열, 즉, 정수 배열의 배열 • TwoDArray.java 참조 (396쪽) • SodaSurvey.java 참조 (397쪽) © 2004 Pearson Addison-Wesley. All rights reserved 7-64 TwoDArray.java // 이차원 배열의 사용을 보인다. public class TwoDArray { // 이차원 정수 배열을 생성하고 // 정수 값들을 오름차순으로 채운 뒤 프린트한다. public static void main (String[] args) { int[][] table = new int[5][10]; // table에 값을 적재한다. for (int row=0; row < table.length; row++) for (int col=0; col < table[row].length; col++) table[row][col] = row * 10 + col; } } // table를 프린트한다. for (int row=0; row < table.length; row++) { for (int col=0; col < table[row].length; col++) System.out.print (table[row][col] + "\t"); System.out.println(); } © 2004 Pearson Addison-Wesley. All rights reserved 7-65 TwoDArray.java 실행 결과 0 10 20 30 40 1 2 3 11 12 21 22 31 32 41 42 4 13 23 33 43 5 14 24 34 44 6 15 25 35 45 © 2004 Pearson Addison-Wesley. All rights reserved 7 16 26 36 46 8 9 17 18 27 28 37 38 47 48 19 29 39 49 7-66 SodaSurvey.java (1/2) // 이차원 배열의 용법을 보인다. import java.text.DecimalFormat; public class SodaSurvey { // 조사 점수의 각 행(소다)과 각 열(응답자)의 // 평균을 계산하고 인쇄한다. public static void main (String[] args) { int[][] scores = { {3, 4, 5, 2, 1, 4, 3, 2, 4, 4}, {2, 4, 3, 4, 3, 3, 2, 1, 2, 2}, {3, 5, 4, 5, 5, 3, 2, 5, 5, 5}, {1, 1, 1, 3, 1, 2, 1, 3, 2, 4} }; final int SODAS = scores.length; final int PEOPLE = scores[0].length; int[] sodaSum = new int[SODAS]; int[] personSum = new int[PEOPLE]; © 2004 Pearson Addison-Wesley. All rights reserved 7-67 SodaSurvey.java (2/2) for (int soda=0; soda < SODAS; soda++) for (int person=0; person < PEOPLE; person++) { sodaSum[soda] += scores[soda][person]; personSum[person] += scores[soda][person]; } DecimalFormat fmt = new DecimalFormat ("0.#"); System.out.println ("Averages:\n"); for (int soda=0; soda < SODAS; soda++) System.out.println ("Soda #" + (soda+1) + ": " + fmt.format ((float)sodaSum[soda]/PEOPLE)); } System.out.println (); for (int person =0; person < PEOPLE; person++) System.out.println ("Person #" + (person+1) + ": " + fmt.format ((float)personSum[person]/SODAS)); }© 2004 Pearson Addison-Wesley. All rights reserved 7-68 SodaSurvey.java 실행 결과 Averages: Soda Soda Soda Soda #1: #2: #3: #4: Person Person Person Person Person Person Person Person Person Person 3.2 2.6 4.2 1.9 #1: 2.2 #2: 3.5 #3: 3.2 #4: 3.5 #5: 2.5 #6: 3 #7: 2 #8: 2.8 #9: 3.2 #10: 3.8 © 2004 Pearson Addison-Wesley. All rights reserved 7-69 다차원 배열 • 배열은 여러 차원을 가질 수 있으며, 둘 이상의 차원을 가질 경우 다차원 배열(multidimensional array)이라고 불린다. • 각 차원은 이전의 차원을 지정된 개수만큼의 원소들로 분할한다. • 각 차원은 각자의 length 상수를 갖는다. • 각 차원은 배열 참조의 배열이므로, 한 차원 안의 배열들이 서로 다른 길이를 가질 수도 있다. 이 경우 누더기 배열(ragged arrays)이라고도 불린다. © 2004 Pearson Addison-Wesley. All rights reserved 7-70 목차 배열 선언과 사용 객체들의 배열 가변 길이 매개변수 리스트 이차원 배열 ArrayList 클래스 다각형(Polygon) 및 다선분(Polyline) 마우스 이벤트와 키 이벤트 © 2004 Pearson Addison-Wesley. All rights reserved 7-71 ArrayList 클래스 • ArrayList 클래스는 java.util 패키지에 들어있다. • 배열의 단점 크기가 결정되면 고정되어 조정할 수 없다. • ArrayList 클래스 배열과 마찬가지로 숫자 인덱스를 사용하여 값 리스트나 참조 리스트를 저장할 수 있다. 필요에 따라 용량을 조절하며 커지거나 줄어들 수 있다. 그러나 ArrayList 객체에 대해 대괄호 구문을 사용할 수는 없다. © 2004 Pearson Addison-Wesley. All rights reserved 7-72 ArrayList 클래스 • 원소들의 삽입이나 삭제 add() 필요한 공간을 마련하기 위해 다른 원소들이 “옆으로 이동한다.” remove() 틈을 없애기 위해 리스트가 “합쳐진다.” © 2004 Pearson Addison-Wesley. All rights reserved 7-73 ArrayList 클래스 • ArrayList Object 클래스에 대한 참조들을 저장하며, 따라서 임의 유형의 객체를 저장할 수 있다. • Beatles.java 참조 (402쪽) • 특정 유형의 객체를 저장하도록 ArrayList 정의할 수도 있다. • 예: Family 객체들만을 저장하는 ArrayList 객체를 생성한다. ArrayList<Family> reunion = new ArrayList<Family> © 2004 Pearson Addison-Wesley. All rights reserved 7-74 Beatles.java (1/2) // Vector 객체 사용을 보인다. import java.util.ArrayListr; public class Beatles { // 밴드 멤버들의 리스트를 저장하고 수정한다. public static void main (String[] args) { ArrayList band = new ArrayList(); band.add band.add band.add band.add ("Paul"); ("Pete"); ("John"); ("George"); System.out.println (band); int location = band.indexOf ("Pete"); band.remove (location); © 2004 Pearson Addison-Wesley. All rights reserved 7-75 Beatles.java (2/2) 및 실행 결과 System.out.println (band); System.out.println ("At index 1: " + band.get(1)); band.add (2, "Ringo"); } } System.out.println (band); System.out.println ("Size of the band: " + band.size()); 실행 결과 =================== [Paul, Pete, John, George] [Paul, John, George] At index 1; John [Paul, John, Ringo, George] Size of the band: 4 © 2004 Pearson Addison-Wesley. All rights reserved 7-76 목차 배열 선언과 사용 객체들의 배열 가변 길이 매개변수 리스트 이차원 배열 ArrayList 클래스 다각형(Polygon) 및 다선분(Polyline) 마우스 이벤트와 키 이벤트 © 2004 Pearson Addison-Wesley. All rights reserved 7-77 다각형과 다선분 • 배열은 그래픽 처리에도 도움이 될 수 있다. • 예를 들면, 좌표 저장에 배열이 사용될 수 있다. • 다각형은 여러 개의 변을 갖는 닫힌 도형이다. • 다선분은 양 끝 점들이 연결되지 않는다는 점을 제외하면 다각형과 같으며, 속을 채울 수 없다. • Rocket.java 참조 (405쪽) • RocketPanel.java 참조 (406쪽) © 2004 Pearson Addison-Wesley. All rights reserved 7-78 Rocket.java // 다각형과 다선분의 사용을 보인다. import javax.swing.JFrame; public class Rocket { // 이 프로그램의 주 프레임을 생성한다. public static void main (String[] args) { JFrame frame = new JFrame ("Rocket"); frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE); RocketPanel panel = new RocketPanel(); } } frame.getContentPane().add(panel); frame.pack(); frame.setVisible(true); © 2004 Pearson Addison-Wesley. All rights reserved 7-79 Rocket.java 실행 결과 © 2004 Pearson Addison-Wesley. All rights reserved 7-80 RocketPanel.java (1/2) // 다각형과 다선분의 사용을 보인다. import java.applet.JPanel; import java.awt.*; public class RocketPanel extends JPanel { private int[] xRocket = {100, 120, 120, 130, 130, 70, 70, 80, 80}; private int[] yRocket = {15, 40, 115, 125, 150, 150, 125, 115, 40}; private int[] xWindow = {95, 105, 110, 90}; private int[] yWindow = {45, 45, 70, 70}; private int[] xFlame = {70, 70, 75, 80, 90, 100, 110, 115, 120, 130, 130}; private int[] yFlame = {155, 170, 165, 190, 170, 175, 160, 185, 160, 175, 155}; © 2004 Pearson Addison-Wesley. All rights reserved 7-81 RocketPanel.java (2/2) // 구성자: 이 패널의 기본 특성을 설정한다. public RocketPanel() { setBackground (Color.black); setSize (new Dimension(200,200)); } // 다각형을 이용한 로켓 그리기 public void paint (Graphics page) { page.setColor (Color.cyan); page.fillPolygon (xRocket, yRocket, xRocket.length); page.setColor (Color.gray); page.fillPolygon (xWindow, yWindow, xWindow.length); } page.setColor (Color.red); page.drawPolyline (xFlame, yFlame, xFlame.length); }© 2004 Pearson Addison-Wesley. All rights reserved 7-82 Polygon 클래스 • Polygon 클래스는 다각형을 정의하고 그리기 위해 사용될 수 있다. • Polygon 클래스는 java.awt 패키지에 들어있다. • 중복정의되어 있는 drawPolygon 메쏘드와 fillPolygon 메쏘드는 좌표 배열 대신 Polygon 객체 한 개를 매개변수로 취한다. • Polygon 객체는 다각형 좌표에 대한 캡슐화이다. © 2004 Pearson Addison-Wesley. All rights reserved 7-83 목차 배열 선언과 사용 객체들의 배열 가변 길이 매개변수 리스트 이차원 배열 ArrayList 클래스 다각형(Polygon) 및 다선분(Polyline) 마우스 이벤트와 키 이벤트 © 2004 Pearson Addison-Wesley. All rights reserved 7-84 마우스 이벤트 • 마우스 관련 이벤트는 마우스 이벤트와 마우스 이동 이벤트로 구분된다. • 마우스 이벤트(MouseEvent): 마우스 누르기 (mouse pressed) 마우스 버튼을 아래로 누른다. 마우스 손떼기 (mouse released) 마우스 버튼을 놓는다. 마우스 클릭 (mouse clicked) 마우스 버튼을 아래로 누른 뒤 마우스를 이동하지 않고 그 버튼을 놓는다. 마우스 진입 (mouse entered) 마우스 포인터가 특정 컴포넌트 위로 옮겨간다. 마우스 떠남 (mouse exited) 마우스 포인터가 특정 컴포넌트 위를 떠난다. © 2004 Pearson Addison-Wesley. All rights reserved 7-85 마우스 이벤트 • 마우스 이동 이벤트(MouseMotionEvent): 마우스 이동 (mouse moved) 마우스를 이동한다. 마우스 끌기 (mouse dragged) 마우스 버튼을 누른 채로 마우스를 이동 한다. • 마우스 이벤트 감청자 생성에 사용되는 인터페이스: MouseListener, MouseMotionListener • 마우스 이벤트가 발생할 때, MouseEvent 객체가 적절한 메쏘드에 매개변수로 전달된다. © 2004 Pearson Addison-Wesley. All rights reserved 7-86 마우스 이벤트 • 하나의 프로그램에서 보통 한 두개 정도의 마우스 이벤트만을 이용하게 된다. • 감청자 인터페이스 구현 조건을 충족시키기 위해, 사용되지 않은 이벤트들에 대해서도 공백 메쏘드가 제공되어야 한다. • Dots.java 참조 (410쪽) • DotsPanel.java 참조 (411쪽) © 2004 Pearson Addison-Wesley. All rights reserved 7-87 Dots.java // 마우스 이벤트들을 보인다. import javax.swing.JFrame; public class Dots { // 응용 프레임을 생성하여 디스플레이한다. public static void main (String[] args) { JFrame frame = new JFrame ("Dots"); frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE); frame.getContentPane().add (new DotsPanel()); } } frame.pack(); frame.setVisible(true); © 2004 Pearson Addison-Wesley. All rights reserved 7-88 Dots.java 실행 결과 © 2004 Pearson Addison-Wesley. All rights reserved 7-89 DotsPanel.java (1/3) // Dots 프로그램의 주 패널을 나타낸다. import import import import java.util.ArrayList; javax.swing.JPanel; java.awt.*; java.awt.event.*; public class DotsPanel extends JPanel { private final int SIZE = 6; // 각 점의 반지름 private ArrayList<Point> pointList; © 2004 Pearson Addison-Wesley. All rights reserved 7-90 DotsPanel.java (2/3) // 구성자: 마우스 이벤트들을 감청하도록 설정한다. public DotsPanel() { pointList = new ArrayList<Point>(); addMouseListener (new DotsListener()); } setBackground (Color.black); setPreferredSize (new Dimension(300, 200)); // 리스트에 저장되어 있는 모든 점들을 그린다. public void paintComponent (Graphics page) { super.paintComponent(page); page.setColor (Color.green); for (Point spot : pointList) page.fillOval (spot.x-SIZE, spot.y-SIZE, SIZE*2, SIZE*2); } page.drawString ("Count: " + pointList.size(), 5, 15); © 2004 Pearson Addison-Wesley. All rights reserved 7-91 DotsPanel.java (3/3) // 마우스 이벤트들을 위한 감청자들을 표현한다. private class DotsListener implements MouseListener { // 현재 점을 점들의 리스트에 추가하고 // 마우스 버튼이 눌려질 때마다 다시 그린다. public void mousePressed (MouseEvent event) { pointList.add(event.getPoint()); repaint(); } } } // 사용되지 않는 이벤트들에 대해 공백 메쏘드를 포함한다. public void mouseClicked (MouseEvent event) {} public void mouseReleased (MouseEvent event) {} public void mouseEntered (MouseEvent event) {} public void mouseExited (MouseEvent event) {} © 2004 Pearson Addison-Wesley. All rights reserved 7-92 마우스 이벤트 • 고무줄 효과(Rubberbanding)란 마우스를 끌어 도형을 “늘이는” 시각적 효과를 말한다. • 다음 예제는 마우스를 끌어 선분을 연속적으로 다시 그린다. • RubberLines.java 참조 (413쪽) • RubberLinesPanel.java 참조 (414쪽) © 2004 Pearson Addison-Wesley. All rights reserved 7-93 RubberLines.java // 이벤트, 감청자, 고무줄 효과를 보여준다. import javax.swing.JFrame; public class RubberLines { // 응용 프레임을 생성하고 디스플레이 한다. public static void main (String[] args) { JFrame frame = new JFrame ("Rubber Lines"); frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE); frame.getContentPane().add (new RubberLinesPanel()); } } frame.pack(); frame.setVisible(true); © 2004 Pearson Addison-Wesley. All rights reserved 7-94 RubberLines.java 실행 결과 © 2004 Pearson Addison-Wesley. All rights reserved 7-95 RubberLinesPanel.java (1/3) import javax.swing.JPanel; import java.awt.*; import java.awt.event.*; public class RubberLinesPanel extends JPanel { private Point point1 = null, point2 = null; // 구성자: 이 패널이 마우스 이벤트들을 감청하도록 설정한다. public RubberLinesPanel() { LineListener listener = new LineListener(); addMouseListener (listener); addMouseMotionListener (listener); } setBackground (Color.black); setPreferredSize (new Dimension(400, 200)); © 2004 Pearson Addison-Wesley. All rights reserved 7-96 RubberLinesPanel.java (2/3) // 처음 마우스가 눌려진 곳부터 마우스의 현재 위치까지 선분을 그린다. public void paintComponent (Graphics page) { super.paintComponent (page); } page.setColor (Color.yellow); if (point1 != null && point2 != null) page.drawLine (point1.x, point1.y, point2.x, point2.y); // 모든 마우스 이벤트들을 위한 감청자를 나타낸다. private class LineListener implements MouseListener, MouseMotionListener { // 마우스 버튼이 눌려진 처음 지점을 포착한다. public void mousePressed (MouseEvent event) { point1 = event.getPoint(); } © 2004 Pearson Addison-Wesley. All rights reserved 7-97 RubberLinesPanel.java (3/3) // 마우스가 끌려짐에 따라 그것의 현재 위치를 구해서, // 고무줄 효과가 생기도록 선분을 그린다. public void mouseDragged (MouseEvent event) { point2 = event.getPoint(); repaint(); } } } // 사용하지 않는 이벤트 메쏘드들을 위한 공백 정의를 제공한다. public void mouseClicked (MouseEvent event) {} public void mouseReleased (MouseEvent event) {} public void mouseEntered (MouseEvent event) {} public void mouseExited (MouseEvent event) {} public void mouseMoved (MouseEvent event) {} © 2004 Pearson Addison-Wesley. All rights reserved 7-98 키 이벤트 • 키 이벤트(KeyEvent)는 사용자가 키보드를 타이핑할 때 발생된다. 키 누르기 (key pressed) 키보드 상의 키를 누른다. 키 손떼기 (key released) 키보드 상의 키에서 손을 뗀다. 키 타이핑 (key typed) 키보드 상의 키를 눌렀다 손을 뗀다. • 키 이벤트 감청자 생성에 사용되는 인터페이스: KeyListener • 키 이벤트가 발생할 때, KeyEvent 객체가 적절한 메쏘드에 매개변수로 전달된다. © 2004 Pearson Addison-Wesley. All rights reserved 7-99 키 이벤트 • 현재 키보드 초점(keyboard focus)을 갖고 있는 컴포넌트가 키 이벤트를 발생시킨다. • KeyEvent 클래스 안의 상수들은 어느 키가 눌려져 있는지를 결정하기 위해 사용될 수 있다. • 다음 예제는 사용자가 화살표 키들을 타이핑할 때 화살표 이미지를 “이동시킨다.” • Direction.java 참조 (417쪽) • DirectionPanel.java 참조 (418쪽) © 2004 Pearson Addison-Wesley. All rights reserved 7-100 Direction.java // 키 이벤트를 시연한다. import javax.swing.JFrame; public class Direction { // 응용 프레임을 생성하고 디스플레이 한다. public static void main (String[] args) { JFrame frame = new JFrame ("Direction"); frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE); frame.getContentPane().add (new DirectionPanel()); } } frame.pack(); frame.setVisible(true); © 2004 Pearson Addison-Wesley. All rights reserved 7-101 Direction.java 실행 결과 © 2004 Pearson Addison-Wesley. All rights reserved 7-102 DirectionPanel.java (1/4) // Direction 프로그램을 위한 주 디스플레이 패널을 나타낸다. import javax.swing.*; import java.awt.*; import java.awt.event.*; public class DirectionPanel extends JPanel { private final int WIDTH = 300, HEIGHT = 200; private final int JUMP = 10; // 이미지 이동을 위한 증가 양 private final int IMAGE_SIZE = 31; private ImageIcon up, down, right, left, currentImage; private int x, y; © 2004 Pearson Addison-Wesley. All rights reserved 7-103 DirectionPanel.java (2/4) // 구성자: 이 패널을 설정하고 이미지들을 적재한다. public DirectionPanel() { addKeyListener (new DirectionListener()); x = WIDTH / 2; y = HEIGHT / 2; up = new ImageIcon ("arrowUp.gif"); down = new ImageIcon ("arrowDown.gif"); left = new ImageIcon ("arrowLeft.gif"); right = new ImageIcon ("arrowRight.gif"); currentImage = right; } setBackground (Color.black); setPreferredSize (new Dimension(WIDTH, HEIGHT)); setFocusable(true); © 2004 Pearson Addison-Wesley. All rights reserved 7-104 DirectionPanel.java (3/4) // 현재 위치에 이미지를 그린다. public void paintComponent (Graphics page) { super.paintComponent (page); currentImage.paintIcon (this, page, x, y); } © 2004 Pearson Addison-Wesley. All rights reserved 7-105 DirectionPanel.java (4/4) // 키보드 동작을 위한 감청자를 표현한다. private class DirectionListener implements KeyListener { // 화살표 키를 누른 사용자에 대해 이미지 및 이미지의 위치를 // 적절히 조정함으로써 반응한다. public void keyPressed (KeyEvent event) { switch (event.getKeyCode()) { case KeyEvent.VK_UP: currentImage = up; y -= JUMP; break; case KeyEvent.VK_DOWN: currentImage = down; y += JUMP; break; case KeyEvent.VK_LEFT: currentImage = left; x -= JUMP; break; case KeyEvent.VK_RIGHT: currentImage = right; x += JUMP; break; } } } } repaint(); // 사용하지 않는 이벤트 메쏘드들을 위한 공백 정의를 제공한다. public void keyTyped (KeyEvent event) {} public void keyReleased (KeyEvent event) {} © 2004 Pearson Addison-Wesley. All rights reserved 7-106 요약 • 7장의 내용: 배열 선언과 사용 경계 검사 및 용량 객체 참조를 저장하는 배열 가변 길이 매개변수 리스트 다차원 배열 ArrayList 클래스 다각형과 다선분 마우스 이벤트와 키보드 이벤트 © 2004 Pearson Addison-Wesley. All rights reserved 7-107