public class ExecClass {
public static void main(String[] args) {
// 1. List
// ListTest listTest = new ListTest();
// listTest.doAction();
// 2. Set
// SetTest setTest = new SetTest();
// setTest.doAction();
// 3. Map
// MapTest mapTest = new MapTest();
// mapTest.doAction();
}
}
1. List
가변 배열이라 볼 수 있다.
List
인덱스 접근
순서 O
중복 O
ArrayList
배열과 유사하다. 순서대로 메모리에 배정
LinkedList
배열과 달리 메모리 주소를 순서대로 연결
무엇이 다를까?
Array (배열) : 처음 만들 때부터 메모리 공간에 필요한 공간 만큼 만들어 사용한다. (연속적) 첫 번째 주소 하나만 알고 있고 그 안에서 인덱스로 접근한다. (메모리 사용은 적지만 활용이 불편함)
List (리스트) : 처음 만들 때 메모리 공간에 하나만 만들고, 추가가 되면 그때 새로운 메모리 공간에 하나를 만들고 메모리 앞뒤 메모리 주소끼리 연결을 해준다. (불연속적이어도 상관 없음) 각각의 메모리 공간을 각각의 메모리 주소로 접근한다. (메모리 사용이 많음)(체인 구조로 연결되기 때문에 데이터가 많아지면 시간이 오래 걸린다. 50번을 찾으려면 1번에서 2번으로 가서 2번에서 3번으로 가서... 50번을 가야한다.)
자료의 삽입, 삭제가 빈번히 일어나는 곳에서는 LinkedList는 사용하면 안 된다! 왠만하면 안 쓰는게 좋음! 삽입, 삭제 비용이 매우 큼.
따라서 현재는 대부분 순서대로 메모리에 배정되는 배열과 유사한 ArrayList를 사용한다.
import java.util.Arrays;
import java.util.ArrayList;
import java.util.LinkedList;
public class ListTest {
public void doAction() {
System.out.println("Array 배열");
// int[] arr = new int[5];
// arr[0] = 7;
int[] arr = {7,9,14,16,31};
System.out.println("arr : " + Arrays.toString(arr));
System.out.println("arr[2] : " + arr[2]);
System.out.println("\n ArrayList 리스트");
ArrayList<Integer> al = new ArrayList<Integer>();
al.add(7);
al.add(9);
al.add(14);
al.add(16);
al.add(31);
System.out.println("al : " + al);
System.out.println("al.equals(14) : " + al.equals(14) + " <- equals로는 값의 비교가 되지 않는다.");
System.out.println("al.indexOf(2) : " + al.indexOf(2)); // 2가 없기 때문에 -1(false)를 반환.
System.out.println("al.indexOf(14) : " + al.indexOf(14)); // 14가 있기 때문에 14의 인덱스 2를 반환.
System.out.println("al.size()) : " + al.size());
al.add(14);
System.out.println("al.size()) : " + al.size() + " 중복 허용 O [7, 16, 14, 31, 9] 이 입력된 상태에서 al.add(16)을 한 번 더 하였더니 추가.");
System.out.println("\n LinkedList 리스트");
LinkedList<Integer> ll = new LinkedList<Integer>();
ll.add(7);
ll.add(9);
ll.add(14);
ll.add(16);
ll.add(31);
System.out.println("ll : " + ll);
}
}
결과 :
Array 배열
arr : [7, 9, 14, 16, 31]
arr[2] : 14
ArrayList 리스트
al : [7, 9, 14, 16, 31]
al.equals(14) : false <- equals로는 값의 비교가 되지 않는다.
al.indexOf(2) : -1
al.indexOf(14) : 2
al.size()) : 5
al.size()) : 6 중복 허용 O [7, 16, 14, 31, 9] 이 입력된 상태에서 al.add(16)을 한 번 더 하였더니 추가.
LinkedList 리스트
ll : [7, 9, 14, 16, 31]
2. Set
속도가 빠르지만 단순 집합 개념으로 정렬 시 별도의 처리가 필요하다. TreeSet은 정렬로 인해 저장하는데 시간이 오래 걸린다.
Set
인덱스 접근
순서 X
중복 X
HsahSet
입력된 값을 무작위로 담는다
LinkedHashSet
입력된 순서대로 담는다
TreeSet
값을 정렬해서 담는다
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.TreeSet;
public class SetTest {
public void doAction( ) {
System.out.println("HashSet");
HashSet<Integer> hs = new HashSet<Integer>();
hs.add(7);
hs.add(16);
hs.add(14);
hs.add(31);
hs.add(9);
System.out.println("hs : " + hs + " 무작위로 담는다.");
System.out.println("hs.equals(14) : " + hs.equals(14) + " <- equals로는 값의 비교가 되지 않는다.");
System.out.println("Set에는 .indexOf()가 존재하지 않는다.");
hs.add(16);
System.out.println("hs.size() : " + hs.size() + " 중복 허용 X [7, 16, 14, 31, 9] 이 입력된 상태에서 hs.add(16)을 한 번 더 하였으나 추가되지 않음.");
System.out.println("\n LinkedHashSet");
LinkedHashSet<Integer> lhs = new LinkedHashSet<Integer>();
lhs.add(7);
lhs.add(16);
lhs.add(14);
lhs.add(31);
lhs.add(9);
System.out.println("lhs : " + lhs + " 입력된 순서대로 담는다.");
System.out.println("\n TreeSet");
TreeSet<Integer> ts = new TreeSet<Integer>();
ts.add(7);
ts.add(16);
ts.add(14);
ts.add(31);
ts.add(9);
System.out.println("ts : " + ts + " 값을 정렬해서 담는다.");
// Set to Array
System.out.println("\n Set to Array");
Object[] o1 = hs.toArray();
System.out.println(Arrays.toString(o1));
}
}
결과 :
HashSet
hs : [16, 7, 9, 14, 31] 무작위로 담는다.
hs.equals(14) : false <- equals로는 값의 비교가 되지 않는다.
Set에는 .indexOf()가 존재하지 않는다.
hs.size() : 5 중복 허용 X [7, 16, 14, 31, 9] 이 입력된 상태에서 hs.add(16)을 한 번 더 하였으나 추가되지 않음.
LinkedHashSet
lhs : [7, 16, 14, 31, 9] 입력된 순서대로 담는다.
TreeSet
ts : [7, 9, 14, 16, 31] 값을 정렬해서 담는다.
Set to Array
[16, 7, 9, 14, 31]
3. Map
속도가 빠르지만 Key의 검색 속도가 속도를 좌우한다. TreeMap은 정렬로 인해 저장하는데 시간이 오래 걸린다.
Map
Key : Value 접근
순서 X
Key 중복 X Value 중복 O
HashMap
입력된 Key : Value 쌍을 무작위로 담는다.
LinkedMap
입력된 순서대로 Key: Value 쌍을 담는다.
TreeMap
Key를 기준으로 정렬해서 담는다.
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.TreeMap;
public class MapTest {
public void doAction() {
System.out.println("HashMap");
HashMap<String, Integer> hm = new HashMap<String, Integer>();
hm.put("alpha", 7);
hm.put("gamma", 14);
hm.put("delta", 31);
hm.put("beta", 16);
hm.put("epsilon", 9);
System.out.println("hm : " + hm + " 무작위로 담는다.");
System.out.println("hm.equals(14) : " + hm.equals(14) + " <- equals로는 값의 비교가 되지 않는다.");
System.out.println("Map에는 .indexOf()가 존재하지 않는다.");
System.out.println("hm.get(\"alpha\") : " + hm.get("alpha") + " Key로 Value를 조회.");
System.out.println("hm.size() : " + hm.size());
hm.put("alpha", 25);
System.out.println("hm.size() : " + hm.size() + " Key 중복 허용 X {epsilon=9, alpha=7, delta=31, beta=16, gamma=14}이 입력된 상태에서 hm.put(\"alpha\", 25)를 한 번 더 하였으나 추가되지 않음.");
hm.put("zeta", 14);
System.out.println("hm.size() : " + hm.size() + " Value 중복 허용 O {epsilon=9, alpha=7, delta=31, beta=16, gamma=14}이 입력된 상태에서 hm.put(\"zeta\", 14)를 한 번 더 하였더니 추가.");
System.out.println("\n LinkedHashMap");
LinkedHashMap<String, Integer> lhm = new LinkedHashMap<String, Integer>();
lhm.put("alpha", 7);
lhm.put("gamma", 14);
lhm.put("delta", 31);
lhm.put("beta", 16);
lhm.put("epsilon", 9);
System.out.println("hm : " + hm + " 입력된 순서대로 담는다.");
System.out.println("\n TreeMap");
TreeMap<String, Integer> tm = new TreeMap<String, Integer>();
tm.put("alpha", 7);
tm.put("gamma", 14);
tm.put("delta", 31);
tm.put("beta", 16);
tm.put("epsilon", 9);
System.out.println("tm : " + tm + " Key로 정렬해서 담는다. (ABCD순)");
}
}
결과 :
HashMap
hm : {epsilon=9, alpha=7, delta=31, gamma=14, beta=16} 무작위로 담는다.
hm.equals(14) : false <- equals로는 값의 비교가 되지 않는다.
Map에는 .indexOf()가 존재하지 않는다.
hm.get("alpha") : 7 Key로 Value를 조회.
hm.size() : 5
hm.size() : 5 Key 중복 허용 X {epsilon=9, alpha=7, delta=31, beta=16, gamma=14}이 입력된 상태에서 hm.put("alpha", 25)를 한 번 더 하였으나 추가되지 않음.
hm.size() : 6 Value 중복 허용 O {epsilon=9, alpha=7, delta=31, beta=16, gamma=14}이 입력된 상태에서 hm.put("zeta", 14)를 한 번 더 하였더니 추가.
LinkedHashMap
hm : {epsilon=9, zeta=14, alpha=25, delta=31, gamma=14, beta=16} 입력된 순서대로 담는다.
TreeMap
tm : {alpha=7, beta=16, delta=31, epsilon=9, gamma=14} Key로 정렬해서 담는다. (ABCD순)
아래는 자바스크립트 기준인데 비슷하겠지...
hashmap.size()returns the # of elements in the hashmap
hashmap.get(<key>)returns the value of the element of the given key
hashmap.has(<key>)checks to see if the hashmap contains the key that is passed as an argument
hashmap.set(<key>, <value>)accepts 2 arguments and creates a new element to the hashmap
hashmap.delete(<key>)deletes the key/value pair that matches the key that is passed in as an argument
hashmap.clear()clears all elements from the hashmap
'{1, 2, 10, 390, 5, 20, 8, 7}' 배열이 있습니다. 인덱스를 선택해 주세요.
9
java.lang.ArrayIndexOutOfBoundsException: Index 9 out of bounds for length 8
e.getMessage() 를 이용한 오류 메시지 출력
이 방법은 오류 메시지를 String 타입으로 받아오기만 해서 e.printStackTrace처럼 바로 콘솔에 뿌려주지 않는다. 따라서 print를 직접 해줘야한다.
'{1, 2, 10, 390, 5, 20, 8, 7}' 배열이 있습니다. 인덱스를 선택해 주세요.
9
Index 9 out of bounds for length 8 오류 발생
2. try ~ catch
에러가 발생할만한 곳에 try를 하고 에러를 catch로 잡는다.
모든 에러의 부모는 (Exception e)로 catch할 수 있으며, 각 에러 타입별로 catch하고 싶다면 아래와 같이 각 에러 타입별로 catch할 수 있다. (ArrayIndexOutOfBoundsException e) : (InputMismatchException e) :
import java.util.Scanner;
import java.util.InputMismatchException;
public class ExecClass {
// 1. try ~ catch 를 활용한 exception 예외처리. (예외가 발생할만한 곳에 try 처리를 한다.)
public static void main(String[] args) {
ExTest exTest = new ExTest();
try {
exTest.doAction();
} catch (Exception e) {
// TODO: handle exception
System.out.println(e.getMessage());
}
}
// // 2. throws Exception (예외가 발생 시 호출한 곳으로 가져와 처리를 한다.)
// public static void main(String[] args){ // 처리할 곳이 있다면... throws Exception으로 ExTest의 doAction2에서 받아온 에러를 다시 위로 던질 수도 있다.
// ExTest exTest = new ExTest();
// Scanner scanner = new Scanner(System.in);
// for (int i = 0; i < 99; i++) {
// try {
// exTest.doAction2();
// } catch (ArrayIndexOutOfBoundsException e) { // try에서 발생한 에러가 인덱스를 벗어난 경우를 catch한다. (인덱스 범위가 0~7인데 8이 들어오는 경우)
// System.out.println("인덱스의 범위를 벗어났습니다. 0 ~ 7 사이로 입력해주세요.");
// } catch (InputMismatchException e) { // try에서 발생한 에러가 데이터 타입이 잘못된 경우를 catch한다. (문자에 숫자가 들어오거나, 숫자에 문자가 들어오는 경우)
// scanner.nextLine(); // int에 잘못 들어와 소거되지 못 하고 무한루프를 발생시키는 문자 찌꺼기 소거용.
// System.out.println("문자를 입력했습니다. 숫자를 입력해주세요.");
// } catch (Exception e) { // 모든 Exception의 부모형태다. 항상 마지막에는 Exception e로 끝내준다. 이 경우는 위에서 인덱스 범위 초과, 데이터 입 에러를 모두 잡아서 마지막 Exception e는 타지 않는다.
// // 위에서 모든 에러를 잡았더라도 혹시 모를 에러에 대비하기 위해 마지막에 모든 에러의 부모형인 Exception e로 끝내줘야한다.
// // 오류 출력 방법 1. e.printStackTrace()
// e.printStackTrace(); // 프로그램이 죽지는 않고 에러메세지를 출력해준다.
// // 오류 출력 방법 2. System.out.println(e.getMessage())
// System.out.println(e.getMessage() + " 오류 발생");
// }
// System.out.println("------------------------------------");
// }
// }
}
import java.util.InputMismatchException;
import java.util.Scanner;
public class ExTest {
// 1. try ~ catch 를 활용한 exception 예외처리. (예외가 발생할만한 곳에 try 처리를 한다.)
public void doAction() {
// TODO Auto-generated method stub
int[] arr = {1, 2, 10, 390, 5, 20, 8, 7};
Scanner scanner = new Scanner(System.in);
// 1.1 try ~ catch 사용의 올바른 예
for (int i = 0; i < 99; i++) {
System.out.println("'{1, 2, 10, 390, 5, 20, 8, 7}' 배열이 있습니다. 인덱스를 선택해 주세요.");
try {
int inputNumber = scanner.nextInt();
scanner.nextLine(); // nextInt return 찌꺼기 소거용.
System.out.println("입력된 숫자에 해당되는 값은 " + arr[inputNumber]);
} catch (ArrayIndexOutOfBoundsException e) { // try에서 발생한 에러가 인덱스를 벗어난 경우를 catch한다. (인덱스 범위가 0~7인데 8이 들어오는 경우)
System.out.println("인덱스의 범위를 벗어났습니다. 0 ~ 7 사이로 입력해주세요.");
} catch (InputMismatchException e) { // try에서 발생한 에러가 데이터 타입이 잘못된 경우를 catch한다. (문자에 숫자가 들어오거나, 숫자에 문자가 들어오는 경우)
scanner.nextLine(); // int에 잘못 들어와 소거되지 못 하고 무한루프를 발생시키는 문자 찌꺼기 소거용.
System.out.println("문자를 입력했습니다. 숫자를 입력해주세요.");
} catch (Exception e) { // 모든 Exception의 부모형태다. 항상 마지막에는 Exception e로 끝내준다. 이 경우는 위에서 인덱스 범위 초과, 데이터 입 에러를 모두 잡아서 마지막 Exception e는 타지 않는다.
// 위에서 모든 에러를 잡았더라도 혹시 모를 에러에 대비하기 위해 마지막에 모든 에러의 부모형인 Exception e로 끝내줘야한다.
// 오류 출력 방법 1. e.printStackTrace()
e.printStackTrace(); // 프로그램이 죽지는 않고 에러메세지를 출력해준다.
// 오류 출력 방법 2. System.out.println(e.getMessage())
System.out.println(e.getMessage() + " 오류 발생");
}
System.out.println("------------------------------------");
}
// // 1.2 try ~ catch 사용의 잘못된 예
// try {
// int inputNumber = scanner.nextInt();
// System.out.println("입력된 숫자에 해당되는 값은 " + arr[inputNumber]);
// } catch (Exception e) { // 얘는 위로 올라오면 안 된다. 모든 Exception의 부모이기 때문에 반드시 마지막으로 가야한다.
// System.out.println("오류 발생");
// } catch (ArrayIndexOutOfBoundsException e) {
// System.out.println("인덱스의 범위를 벗어났습니다.");
// }
}
// 2. throws Exception (예외가 발생 시 호출한 곳으로 가져와 처리를 한다.)
public void doAction2() throws Exception { // 에러 발생시 호출한 곳으로 보낼거야.
// TODO Auto-generated method stub
int[] arr = {1, 2, 10, 390, 5, 20, 8, 7};
System.out.println("'{1, 2, 10, 390, 5, 20, 8, 7}' 배열이 있습니다. 인덱스를 선택해 주세요.");
Scanner scanner = new Scanner(System.in);
int inputNumber = scanner.nextInt(); // 여기서는 에러 처리를 하지 않는다. 에러 발생시 호출한 곳으로 에러를 던진다.
scanner.nextLine(); // nextInt return 찌꺼기 소거용.
System.out.println("입력된 숫자에 해당되는 값은 " + arr[inputNumber]);
}
}
결과 :
'{1, 2, 10, 390, 5, 20, 8, 7}' 배열이 있습니다. 인덱스를 선택해 주세요.
7
입력된 숫자에 해당되는 값은 7
------------------------------------
'{1, 2, 10, 390, 5, 20, 8, 7}' 배열이 있습니다. 인덱스를 선택해 주세요.
8
인덱스의 범위를 벗어났습니다. 0 ~ 7 사이로 입력해주세요.
------------------------------------
'{1, 2, 10, 390, 5, 20, 8, 7}' 배열이 있습니다. 인덱스를 선택해 주세요.
a
문자를 입력했습니다. 숫자를 입력해주세요.
------------------------------------
'{1, 2, 10, 390, 5, 20, 8, 7}' 배열이 있습니다. 인덱스를 선택해 주세요.
3. throws exception
예외가 발생 시 호출한 곳으로 가져와 처리를 한다. (일반적으로 throws보다는 예외 발생 부분에서 surround try ~ catch를 하는게 좋다.)
import java.util.Scanner;
import java.util.InputMismatchException;
public class ExecClass {
// // 1. try ~ catch 를 활용한 exception 예외처리. (예외가 발생할만한 곳에 try 처리를 한다.)
// public static void main(String[] args) {
// ExTest exTest = new ExTest();
// try {
// exTest.doAction();
// } catch (Exception e) {
// // TODO: handle exception
// System.out.println(e.getMessage());
// }
// }
// 2. throws Exception (예외가 발생 시 호출한 곳으로 가져와 처리를 한다.)
public static void main(String[] args){ // 처리할 곳이 있다면... throws Exception으로 ExTest의 doAction2에서 받아온 에러를 다시 위로 던질 수도 있다.
ExTest exTest = new ExTest();
Scanner scanner = new Scanner(System.in);
for (int i = 0; i < 99; i++) {
try {
exTest.doAction2();
} catch (ArrayIndexOutOfBoundsException e) { // try에서 발생한 에러가 인덱스를 벗어난 경우를 catch한다. (인덱스 범위가 0~7인데 8이 들어오는 경우)
System.out.println("인덱스의 범위를 벗어났습니다. 0 ~ 7 사이로 입력해주세요.");
} catch (InputMismatchException e) { // try에서 발생한 에러가 데이터 타입이 잘못된 경우를 catch한다. (문자에 숫자가 들어오거나, 숫자에 문자가 들어오는 경우)
scanner.nextLine(); // int에 잘못 들어와 소거되지 못 하고 무한루프를 발생시키는 문자 찌꺼기 소거용.
System.out.println("문자를 입력했습니다. 숫자를 입력해주세요.");
} catch (Exception e) { // 모든 Exception의 부모형태다. 항상 마지막에는 Exception e로 끝내준다. 이 경우는 위에서 인덱스 범위 초과, 데이터 입 에러를 모두 잡아서 마지막 Exception e는 타지 않는다.
// 위에서 모든 에러를 잡았더라도 혹시 모를 에러에 대비하기 위해 마지막에 모든 에러의 부모형인 Exception e로 끝내줘야한다.
// 오류 출력 방법 1. e.printStackTrace()
e.printStackTrace(); // 프로그램이 죽지는 않고 에러메세지를 출력해준다.
// 오류 출력 방법 2. System.out.println(e.getMessage())
System.out.println(e.getMessage() + " 오류 발생");
}
System.out.println("------------------------------------");
}
}
}
import java.util.InputMismatchException;
import java.util.Scanner;
public class ExTest {
// 1. try ~ catch 를 활용한 exception 예외처리. (예외가 발생할만한 곳에 try 처리를 한다.)
public void doAction() {
// TODO Auto-generated method stub
int[] arr = {1, 2, 10, 390, 5, 20, 8, 7};
Scanner scanner = new Scanner(System.in);
// 1.1 try ~ catch 사용의 올바른 예
for (int i = 0; i < 99; i++) {
System.out.println("'{1, 2, 10, 390, 5, 20, 8, 7}' 배열이 있습니다. 인덱스를 선택해 주세요.");
try {
int inputNumber = scanner.nextInt();
scanner.nextLine(); // nextInt return 찌꺼기 소거용.
System.out.println("입력된 숫자에 해당되는 값은 " + arr[inputNumber]);
} catch (ArrayIndexOutOfBoundsException e) { // try에서 발생한 에러가 인덱스를 벗어난 경우를 catch한다. (인덱스 범위가 0~7인데 8이 들어오는 경우)
System.out.println("인덱스의 범위를 벗어났습니다. 0 ~ 7 사이로 입력해주세요.");
} catch (InputMismatchException e) { // try에서 발생한 에러가 데이터 타입이 잘못된 경우를 catch한다. (문자에 숫자가 들어오거나, 숫자에 문자가 들어오는 경우)
scanner.nextLine(); // int에 잘못 들어와 소거되지 못 하고 무한루프를 발생시키는 문자 찌꺼기 소거용.
System.out.println("문자를 입력했습니다. 숫자를 입력해주세요.");
} catch (Exception e) { // 모든 Exception의 부모형태다. 항상 마지막에는 Exception e로 끝내준다. 이 경우는 위에서 인덱스 범위 초과, 데이터 입 에러를 모두 잡아서 마지막 Exception e는 타지 않는다.
// 위에서 모든 에러를 잡았더라도 혹시 모를 에러에 대비하기 위해 마지막에 모든 에러의 부모형인 Exception e로 끝내줘야한다.
// 오류 출력 방법 1. e.printStackTrace()
e.printStackTrace(); // 프로그램이 죽지는 않고 에러메세지를 출력해준다.
// 오류 출력 방법 2. System.out.println(e.getMessage())
System.out.println(e.getMessage() + " 오류 발생");
}
System.out.println("------------------------------------");
}
// // 1.2 try ~ catch 사용의 잘못된 예
// try {
// int inputNumber = scanner.nextInt();
// System.out.println("입력된 숫자에 해당되는 값은 " + arr[inputNumber]);
// } catch (Exception e) { // 얘는 위로 올라오면 안 된다. 모든 Exception의 부모이기 때문에 반드시 마지막으로 가야한다.
// System.out.println("오류 발생");
// } catch (ArrayIndexOutOfBoundsException e) {
// System.out.println("인덱스의 범위를 벗어났습니다.");
// }
}
// 2. throws Exception (예외가 발생 시 호출한 곳으로 가져와 처리를 한다.)
public void doAction2() throws Exception { // 에러 발생시 호출한 곳으로 보낼거야.
// TODO Auto-generated method stub
int[] arr = {1, 2, 10, 390, 5, 20, 8, 7};
System.out.println("'{1, 2, 10, 390, 5, 20, 8, 7}' 배열이 있습니다. 인덱스를 선택해 주세요.");
Scanner scanner = new Scanner(System.in);
int inputNumber = scanner.nextInt(); // 여기서는 에러 처리를 하지 않는다. 에러 발생시 호출한 곳으로 에러를 던진다.
scanner.nextLine(); // nextInt return 찌꺼기 소거용.
System.out.println("입력된 숫자에 해당되는 값은 " + arr[inputNumber]);
}
}
결과 :
'{1, 2, 10, 390, 5, 20, 8, 7}' 배열이 있습니다. 인덱스를 선택해 주세요.
7
입력된 숫자에 해당되는 값은 7
------------------------------------
'{1, 2, 10, 390, 5, 20, 8, 7}' 배열이 있습니다. 인덱스를 선택해 주세요.
8
인덱스의 범위를 벗어났습니다. 0 ~ 7 사이로 입력해주세요.
------------------------------------
'{1, 2, 10, 390, 5, 20, 8, 7}' 배열이 있습니다. 인덱스를 선택해 주세요.
a
문자를 입력했습니다. 숫자를 입력해주세요.
------------------------------------
'{1, 2, 10, 390, 5, 20, 8, 7}' 배열이 있습니다. 인덱스를 선택해 주세요.
3.2 throws execption에 대한 고찰 execption 강제로 발생시켜 위로 던지기
public class ExecClass {
public static void main(String[] args) {
try {
Test1 test1 = new Test1();
test1.doAction();
} catch (Exception e) {
if (e.getMessage().equals("input 1")) {
System.out.println("사용자가 1을 입력했습니다.");
}
}
}
}
import java.util.Scanner;
public class Test1 {
public void doAction() throws Exception {
Scanner s = new Scanner(System.in);
int inputNumber = s.nextInt();
if(inputNumber ==1) {
throw new Exception("input 1");
}
}
}
이 예제를 실행해보면 어떤 것인지 감을 잡을 수 있다.
우선 execption은 에러가 발생시 담아내는 공간이다. 그 중에서도 Execption은 모든 예외의 최상단 부모다. (모든 에러를 다 담을 수 있다.)
// 조건이 참인 경우 실행
if (조건) {
로직
}
// 조건이 에러(execption)인 경우 참이고 그 때 실행
catch (조건) {
로직
}
if ~ else if ~ else 구문은 try ~ catch ~ catch 구문과 크게 다르지 않다.
A클래스가 B 클래스의 메소드를 실행했다. 그런데 B 클래스의 메소드가 에러가 발생할 경우 B가 죽어버린다. 그래서 B는 try ~ catch로 에러가 나도 죽지 않도록 보호를 한다.
하지만 B가 메소드를 throws Execption으로 정의할 경우 B는 에러를 처리하지도 않고, 에러 발생 시 죽는 대신 호출한 쪽에 에러를 담은 execption을 던져준다. 그러면 A가 그 에러를 받게 되는데, 이 때 A가 에러 처리를 하는 로직이 없다면 죽어버린다. 따라서 A가 에러 처리 하는 로직을 넣어주어 보호를 한다.
즉, try ~ catch와 throws Execption의 차이는 에러가 발생 시 프로그램이 죽는 대신 단지 그것을 잡아내 보호하는 로직을 어디에 오려 붙일거냐의 차이다.
위 예제의 경우 B가 Execption에 일부러 값을 넣고 던져 올리니 A는 A가 넣을 값을 가져와 처리하게 되는 것이다. 즉, execption이라는 공간에 값이 있어서 실행한 것이다. 단지 그것 뿐...
public class ExecClass {
public static void main(String[] args) {
// 1. 파는 상품 목록 (표시)
// 2. 메뉴 숫자를 눌러서 구매
// 3. 현재 판매된 누적 금액 표시
// 4. 구매자 만들어서 구매자별 누적 금액 표
// 5. 종료 조건 (-1) 종료
People p1 = new People("홍길동");
People p2 = new People("장보고");
Store store = new Store();
for (int i = 0; i < 9999; i++) {
int select = store.select();
if (select == -1) { // -1이면 종료.
break;
} else if (i % 2 == 0) { // i 가 짝수일 때는 홍길동이 구매.
store.sellItem(p1, select);
} else { // i 가 홀수일 때는 장보고가 구매.
store.sellItem(p2, select);
}
System.out.println("----------------------------------------");
}
System.out.println(p1.name + "이 구매한 총 금액 : " + p1.buyTotal);
System.out.println(p2.name + "이 구매한 총 금액 : " + p2.buyTotal);
}
}
2. People
public class People {
int buyTotal = 0;
String name;
public People(String name) {
// TODO Auto-generated constructor stub
this.name = name;
}
}
3. Item
public class Item {
String name;
int price;
int stock;
public Item(String name, int price, int stock) {
// TODO Auto-generated constructor stub
this.name = name;
this.price = price;
this.stock = stock;
}
}
4. Store
import java.util.Scanner;
public class Store {
Item[] menu;
int sales = 0;
// 1. 생성자. 메뉴를 생성한다.
public Store() {
// TODO Auto-generated constructor stub
menu = new Item[5];
menu[0] = new Item("딸기우유", 1000, 10);
menu[1] = new Item("샌드위치", 2000, 5);
menu[2] = new Item("메로나", 800, 20);
menu[3] = new Item("풍선껌", 500, 2);
menu[4] = new Item("크림빵", 1000, 5);
}
// 2. 메뉴를 출력하는 메소드.
public void showMenu() {
for (int i = 0; i < menu.length; i++) {
System.out.println((i + 1) + ". " + menu[i].name + " : " + menu[i].price);
}
}
// 3. 메뉴를 선택하는 메소드.
int selectNumber;
public int select() {
Scanner s = new Scanner(System.in);
for (int i = 0; i < 99; i++) {
this.showMenu();
System.out.println("구매하고 싶은 메뉴 번호를 입력해주세요. -1 입력 시 종료.");
try {
selectNumber = Integer.parseInt(s.nextLine());
if (selectNumber == -1) {
return -1;
} else if (selectNumber >= 1 && selectNumber <= 5) {
return (selectNumber - 1);
} else {
System.out.println("메뉴 버튼의 숫자만 입력해주세요.");
continue;
}
} catch (Exception e) {
// TODO: handle exception
System.out.println("메뉴 버튼의 숫자만 입력해주세요.");
}
}
return -1;
}
public void sellItem(People people, int number) {
if (menu[number].stock < 1) {
System.out.println("재고가 부족합니다.");
} else {
this.sales = this.sales + menu[number].price;
menu[number].stock--;
System.out.println("판매된 총 금액 : " + this.sales);
people.buyTotal = people.buyTotal + menu[number].price;
System.out.println(menu[number].name + "이(가) " + people.name + "에게 판매되었습니다.");
}
}
}
실행 결과
1. 딸기우유 : 1000
2. 샌드위치 : 2000
3. 메로나 : 800
4. 풍선껌 : 500
5. 크림빵 : 1000
구매하고 싶은 메뉴 번호를 입력해주세요. -1 입력 시 종료.
1
판매된 총 금액 : 1000
딸기우유이(가) 홍길동에게 판매되었습니다.
----------------------------------------
1. 딸기우유 : 1000
2. 샌드위치 : 2000
3. 메로나 : 800
4. 풍선껌 : 500
5. 크림빵 : 1000
구매하고 싶은 메뉴 번호를 입력해주세요. -1 입력 시 종료.
5
판매된 총 금액 : 2000
크림빵이(가) 장보고에게 판매되었습니다.
----------------------------------------
1. 딸기우유 : 1000
2. 샌드위치 : 2000
3. 메로나 : 800
4. 풍선껌 : 500
5. 크림빵 : 1000
구매하고 싶은 메뉴 번호를 입력해주세요. -1 입력 시 종료.
2
판매된 총 금액 : 4000
샌드위치이(가) 홍길동에게 판매되었습니다.
----------------------------------------
1. 딸기우유 : 1000
2. 샌드위치 : 2000
3. 메로나 : 800
4. 풍선껌 : 500
5. 크림빵 : 1000
구매하고 싶은 메뉴 번호를 입력해주세요. -1 입력 시 종료.
3
판매된 총 금액 : 4800
메로나이(가) 장보고에게 판매되었습니다.
----------------------------------------
1. 딸기우유 : 1000
2. 샌드위치 : 2000
3. 메로나 : 800
4. 풍선껌 : 500
5. 크림빵 : 1000
구매하고 싶은 메뉴 번호를 입력해주세요. -1 입력 시 종료.
-1
홍길동이 구매한 총 금액 : 3000
장보고이 구매한 총 금액 : 1800