그동안 배운 판다스 조회가 문제로 나왔다...

풀긴 풀었는데 힘겹게 풀었다 연습이 부족하다...

 

스위프트에는 이제 화면을 3개로 만들고, 서로 다른 화면에 값을 던져 넣어주는 것을 했다.

'개발자 > TIL' 카테고리의 다른 글

TIL 20.05.27  (0) 2020.05.27
TIL 20.05.26  (0) 2020.05.26
TIL 20.05.24  (0) 2020.05.26
TIL 20.05.23  (0) 2020.05.24
TIL 20.05.22  (0) 2020.05.23

자바! 자바! 자바!

'개발자 > TIL' 카테고리의 다른 글

TIL 20.05.26  (0) 2020.05.26
TIL 20.05.25  (0) 2020.05.26
TIL 20.05.23  (0) 2020.05.24
TIL 20.05.22  (0) 2020.05.23
TIL 20.05.21  (0) 2020.05.22

1. ExecClass

import java.util.ArrayList;
import java.util.Comparator;

public class ExecClass {
	public static void main(String[] args) {
		ArrayList<Student> arr = new ArrayList<Student>();
		arr.add(new Student("홍길동",100));
		arr.add(new Student("둘리",10));
		arr.add(new Student("또치",80));
		arr.add(new Student("희동이",50));
		
		// 정렬 이전의 값을 확인하기 위한 출력 부분.
		for (int i = 0; i < arr.size(); i++) {		// 배열과 비슷하나 length가 아닌 size로 접근.
			System.out.println(arr.get(i).name + " : " + arr.get(i).score);		// get(i)로 접근.
		}
		
		System.out.println("--------------------------------------------");
		
		
		// 1. 여기서 바로 구현하자.
//		arr.sort(new Comparator<Student>() {	// generic으로 데이터 타입을 Student로 잡아준다.
//
//			@Override
//			public int compare(Student o1, Student o2) {	// 비교할 대상을 넣는다. Student 클래스 데이터 타입의 객체1(o1), 객체2(o2).
//				// TODO Auto-generated method stub
//				// return에다 내가 정렬하고 싶은 데이터 기준과 오름차순, 내림차순을 구현한다.
//				return o1.score - o2.score;				// score를 기준으로 오름차순 정렬. (10 -> 50 -> 80 -> 100)
//				return o2.score - o1.score;				// score를 기준으로 내림차순 정렬. (100 -> 80 -> 50 -> 10)
//				return o1.name.compareTo(o2.name);		// name을 기준으로 오름차순 정렬. (둘리 -> 또치 -> 홍길동 -> 희동이)
//				return o2.name.compareTo(o1.name);		// name을 기준으로 오름차순 정렬. (희동이 -> 홍길동 -> 또치 -> 둘리)
//				
//				if (o1.name.equals("또치")) {	 // 또치가 나오면 젤 앞으로 보내. (또치 -> 나머지는 그대로)
//					return -1;		// 내림차순.
//				}
//				return 0;
//		
//				if (o1.name.equals("또치")) {	 // 또치가 나오면 젤 아래로 보내.
//					return 1;		// 오름차순.
//				}
//				return 0;
//		
//	
//
//			}
//			
//		});
		
		// 2. StudentCompare를 만들어 따로 분리하자.
		StudentCompare sc = new StudentCompare();
		arr.sort(sc);
		
		
		
		
		// 정렬을 확인하기 위한 출력 부분.
		System.out.println("정렬된 결과는");
		for (int i = 0; i < arr.size(); i++) {
			System.out.println(arr.get(i).name + " : " + arr.get(i).score);
		}

				
	}

}

 

 

2. Student

public class Student {
	String name;
	int score;
	
	Student(String name, int score) {
		this.name = name;
		this.score = score;
	}

}

 

 

3. StudentCompare

import java.util.Comparator;

public class StudentCompare implements Comparator {	// generic을 사용하지 않아 어떤 형태인지 모를 경우 Object 형태로만 사용이 가능하다. 그래서 형변환.

	@Override
	public int compare(Object o1, Object o2) {
		Student s1 = (Student)o1;
		Student s2 = (Student)o2;
		
		return s1.score - s2.score;				// score를 기준으로 오름차순 정렬. (10 -> 50 -> 80 -> 100)
//		return s2.score - s1.score;				// score를 기준으로 내림차순 정렬. (100 -> 80 -> 50 -> 10)
//		return s1.name.compareTo(s2.name);		// name을 기준으로 오름차순 정렬. (둘리 -> 또치 -> 홍길동 -> 희동이)
//		return s2.name.compareTo(s1.name);		// name을 기준으로 오름차순 정렬. (희동이 -> 홍길동 -> 또치 -> 둘리)
		
//		if (s1.name.equals("또치")) {	 // 또치가 나오면 젤 앞으로 보내. (또치 -> 나머지는 그대로)
//			return -1;		// 내림차순.
//		}
//		return 0;
		
//		if (s2.name.equals("또치")) {	 // 또치가 나오면 젤 아래로 보내.
//			return -1;		// 오름차순.
//		}
//		return 0;
	
	}
}


정렬 이전 (입력 순서대로 출력)

홍길동 : 100
둘리 : 10
또치 : 80
희동이 : 50
------------------------------------------------------------------------------
return s1.score - s2.score;				// score를 기준으로 오름차순 정렬. (10 -> 50 -> 80 -> 100)

정렬된 결과는
둘리 : 10
희동이 : 50
또치 : 80
홍길동 : 100
------------------------------------------------------------------------------
return s2.score - s1.score;				// score를 기준으로 내림차순 정렬. (100 -> 80 -> 50 -> 10)

정렬된 결과는
홍길동 : 100
또치 : 80
희동이 : 50
둘리 : 10
------------------------------------------------------------------------------
return s1.name.compareTo(s2.name);		// name을 기준으로 오름차순 정렬. (둘리 -> 또치 -> 홍길동 -> 희동이)

정렬된 결과는
둘리 : 10
또치 : 80
홍길동 : 100
희동이 : 50
------------------------------------------------------------------------------
return s2.name.compareTo(s1.name);		// name을 기준으로 오름차순 정렬. (희동이 -> 홍길동 -> 또치 -> 둘리)

정렬된 결과는
희동이 : 50
홍길동 : 100
또치 : 80
둘리 : 10
------------------------------------------------------------------------------
if (s1.name.equals("또치")) {	 // 또치가 나오면 젤 앞으로 보내. (나머지는 그대로)
	return -1;		// 내림차순.
}
return 0;
        
정렬된 결과는
또치 : 80
홍길동 : 100
둘리 : 10
희동이 : 50
------------------------------------------------------------------------------
if (s2.name.equals("또치")) {	 // 또치가 나오면 젤 아래로 보내. (나머지는 그대로)
	return -1;		// 오름차순.
}
return 0;
        
정렬된 결과는
홍길동 : 100
둘리 : 10
희동이 : 50
또치 : 80

 

 

자바에서 자료구조는 크게 3가지 구조로 나눌 수 있다.


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. 오류 메시지 출력 방법

e.printStackTrace() 를 이용한 오류 메시지 출력

'{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이라는 공간에 값이 있어서 실행한 것이다. 단지 그것 뿐...

 

1. ExecClass

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

오늘은 그동안 밀려있던 자바를 조금 복습했다.

사실 할게 많이 밀렸는데 오늘은 개인적인 일로 너무 힘들어서 많이 하지 못 했다...

나는 현재 같이 수업 듣는 기수에서 부반장으로 선출 되었고, 종료 되었지만 팀프로젝트의 조장이었다.

그런데 우리 기수의 동기이자 내 팀의 조원이었던 사람 한 명을 잃었다.

최대한 챙겨주려고 많이 신경 썼고, 조원들한테도 부탁을 했지만 결국 최근 따라오는데 버거움을 느끼고 그만두었다.

그만 두기 전날 까지만 해도 웃으며 헤어졌는데... 연락 조차 받지 않는 걸 보고 속으로 그 사람의 마음 속 상처가 보이는 것 같아 너무나도 힘들어 하루 종일 울었다.

갑작스럽게 만화 이야기를 꺼내서 쌩뚱맞지만... 원피스에서 루피가 떠오른다. '내가 더 강해지지 않으면 동료를 지킬 수 없다'는 말을 하던 장면...

내가 더 잘 했더라면 그만 두지 않았을 수 있었을텐데...

'개발자 > TIL' 카테고리의 다른 글

TIL 20.05.25  (0) 2020.05.26
TIL 20.05.24  (0) 2020.05.26
TIL 20.05.22  (0) 2020.05.23
TIL 20.05.21  (0) 2020.05.22
TIL 20.05.20  (0) 2020.05.21

오늘은 스위프트로 VeiwController를 여러개 만들어서 화면을 넘기고, 화면을 넘길 때 변수값을 미리 접근해서 바꾸는 것을 공부했다.

 

그리고 자바는 드디어 DB 연동을 시작했다. Spring, Tomcat을 설치했는데 아직 코드가 전혀 눈에 보이지 않고 낯설다.

 

이 또한 시간이 해결해주리라...

'개발자 > TIL' 카테고리의 다른 글

TIL 20.05.24  (0) 2020.05.26
TIL 20.05.23  (0) 2020.05.24
TIL 20.05.21  (0) 2020.05.22
TIL 20.05.20  (0) 2020.05.21
TIL 20.05.19  (0) 2020.05.20

+ Recent posts