-
자바기초개념 다시잡기 자바의정석 - 예외처리/컬렉션프레임/제네릭/쓰레드자바 기초 2021. 8. 2. 18:57
남궁성님의 자바의 정석 - 기초편 유투브 참조!
1. 오류 및 예외
- 프로그램 오류에는 컴파일/런타임/논리적 에로로 나뉜다
- 컴파일에러 - 자바프로그램(이클립스)가 이해하지 못하는 에러(구문-문법/번역/최적화)
- 런타임에러 - 실행중 발생하는 에러 (컴파일시에는 에러가 없지만 프로그램이 실행되면서 특정 상황이나 특정값이 들어갈때등 나타나는 에러 -> A(1) / B(0) 일때 문법은 맞으나 0으로 나눌 수 없으니 런타임 뜸)
- 논리적에러 - 작성의도와 다르게 동작되는 에러
- 자바의 런타임 에러는 크게 두개로 나뉜다
- 에러(error) - 코드에 의해서 수습될 수 없는 '심각한' 오류
- 예외(exception) - 코드에 의해서 수습이 가능한 '미약한' 오류
- 즉 에러는 어쩔수 없지만 예외처리가 가능한 것은 개발자로써 해야한다
- 예외처리로 비정상 종료를 막고 프로그램이 계속해서 정상적으로 실행되도록 유지해야한다
- 예외처리는 Exception과 RuntimeExcetion으로 구분
- Exception - 사용자의 실수와 같은 외적인 요인으로 발생
- RuntimeExcetion - 프로그래머의 실수로 발생
- IOException - 입출력예외
- ClassNotFoundException - 클래스를 찾을 수 없음
- ArithmeticException - 산술계산예외
- ClassCastException - 형변환 예외
- NullPointerException - 어떤 변수 또는 객체가 null인데 호출할 때
- IndexOutOfBoundsException - 배열범위벗어남
- 그외 예외처리시 자주 쓰는 것들
- printStackTrace() - 예외발생시 호출스택에 있었던 메서드의 정보와 예외 메세지를 화면에 출력
- getMessage() - 발생한 예외클래스의 인스턴스에 저장된 메세지를 얻을 수 있음
2. 예외처리하기
- 예외처리는 보통 'try-catch'문으로 처리한다
3. 컬렉션 프레임워크
- 자바의 객체지향 다음으로 가장 중요한 부분
- 여러 자주쓰는 객체 혹은 데이터 등을 모아 표준화/정형화를 시켜놓은 것. 일일이 코드를 짤 필요없이 자주 쓰는 것들은 컬렉션 프레임워크를 호출해서 쓰면 된다(Vector/ArrayList,Hash etc)
- 컬렉션 프레임워크의 핵심은 다수의 데이터를 다루기 위한 것(List/Set/Map)
색이 들어가있는 콜렉션들, 즉 추가,검색,삭제가 많이 쓰인다 3-1 List 인터페이스
- 순서가 정해져 있으며 중복이 허용 된다
- ArrayList/LinkedList가 핵심이다
3-1-1 ArrayList
- 기존 Vector를 개선했고 동기화처리가 가능하며 배열을 기반으로 동작된다
- ArrayList 안의 객체를 '모두' 삭제하려면 반드시 총 사이즈 - 1 을 해야한다 왜냐하면 remove(삭제)의 경우는 데이터를 지우는것이아니라 있던 자리를 null로 대체하고 한칸씩 밀려 올라가기 때문이다. 다 지우고싶으면 반드시 끝에서부터 해야한다
public class Ex_1 { public static void main(String[] args) { ArrayList list1 = new ArrayList(10); list1.add(5); list1.add(4); list1.add(3); list1.add(1); list1.add(2); System.out.println(list1); ArrayList list2 = new ArrayList(list1.subList(0, 2)); System.out.println(list2); } } [5, 4, 3, 1, 2] [5, 4] Collections.sort(list1); System.out.println(list1); [1, 2, 3, 4, 5] list1.add("B"); list1.add(1,"S"); System.out.println(list1); [1, S, 2, 3, 4, 5, B] //set은 변경 list1.set(2, "DD"); System.out.println(list1); [1, S, DD, 3, 4, 5, B] list1.add(0,"1"); System.out.println(list1); System.out.println("index= "+ list1.indexOf("1")); [1, 1, S, DD, 3, 4, 5, B] index= 0 list1.remove(3); System.out.println(list1); list1.remove(new Integer(3)); System.out.println(list1); [1, 1, S, 3, 4, 5, B] [1, 1, S, 4, 5, B]
처음부터 지우면 스택이 올라가기때문에 다 지울 수 없다 반드시 이런 로직으로 지워야 다 지워진다 3-1-2 LinkedList
- 배열 구조가 간단하고 데이터를 읽는 시간이 짧다는 장점이 있지만 크기 변경 불가(변경이 필요하면 새 배열을 생성 후 데이터를 옮기는 구조로 해야한다)
1) 더 큰 배열 생성 -> 2) 원 데이터 복사 -> 3) 참조 변경 - 배열의 단점을 보완한 기능
*컬렉션 프레임 워크 사용시에 데이터를 접근하는데 사용하는 인터페이스 (Iterator)
3-2 HashSet
- Set 인터페이스의 가장 중요한 요소 중 하나로 순서를 유지하지않고 중복을 허용하지 않는다.
(순서 유지는 LinkedHashSet)
public class Ex_2 { public static void main(String[] args) { Object[] arr = {"1", 1, "2","2","3","3","4","4"}; Set set = new HashSet(); for (int i=0; i<arr.length; i++) { System.out.println("arr[i]= " + arr[i]); System.out.println("set.add(arr[i])= " + set.add(arr[i])); } System.out.println(set); } } arr[i]= 1 set.add(arr[i])= true arr[i]= 1 set.add(arr[i])= true arr[i]= 2 set.add(arr[i])= true arr[i]= 2 set.add(arr[i])= false arr[i]= 3 set.add(arr[i])= true arr[i]= 3 set.add(arr[i])= false arr[i]= 4 set.add(arr[i])= true arr[i]= 4 set.add(arr[i])= false [1, 1, 2, 3, 4] Iterator it = set.iterator(); while(it.hasNext()) { System.out.println(it.next()); } 1 1 2 3 4 public class Ex_2 { public static void main(String[] args) { Set set = new HashSet(); for (int i=0; set.size() < 6; i++) { int num = (int)(Math.random()*45) + 1; set.add(num); } List list = new LinkedList(set); //*일반 리스트는 정수만 가능 Collections.sort(list); System.out.println(list); } } [17, 30, 33, 38, 41, 45]
3-3 HashMap
- Map 인터페이스중 하나로 키와 값으로 구현 됨
- 순서에 상관없이 저장 가능하고 중복은 키 제외 값은 중복 가능, 동기화 불가능 (순서 유지 -> LinkedHashMap)
- 해싱 기법으로 데이터를 저장하기때문에 키와 값으로 빠르게 검색이 가능
public class Ex_3 { public static void main(String[] args) { HashMap map = new HashMap(); map.put("aaa", "1234"); map.put("bbb", "1111"); System.out.println(map); map.put("bbb", "1234"); System.out.println(map); {aaa=1234, bbb=1111} {aaa=1234, bbb=1234} HashMap map = new HashMap(); map.put("aaa", "1234"); map.put("bbb", "1111"); map.put("bbb", "1234"); Scanner sc = new Scanner(System.in); while(true) { System.out.println("Enter your ID/PW.>>"); System.out.println("ID:"); String id = sc.nextLine().trim(); //trim() -> 공백제거 System.out.println("PW:"); String pw = sc.nextLine().trim(); System.out.println(); if(!map.containsKey(id)) { System.out.println("Not found. Try again!>>>"); continue; } if(!(map.get(id)).equals(pw)) { System.out.println("The password is incorrect. Try again!>>>"); } else { System.out.println("ID/PW are correct!"); break; } } } } Enter your ID/PW.>> ID: ccc PW: 1111 Not found. Try again!>>> Enter your ID/PW.>> ID: bbb PW: 1234 ID/PW are correct! HashMap map = new HashMap(); map.put("VIC", 95); map.put("CHA", 85); map.put("KIM", 55); map.put("MIN", 77); map.put("RYU", 65); Set set = map.entrySet(); //map에 저장된 모든(entry) 키/값 들고옴 Iterator it = set.iterator(); while (it.hasNext()) { Map.Entry e = (Map.Entry)it.next(); //entrySet과 같은 기능으로 객체처럼 쓸때 System.out.println("Name: "+e.getKey()+", Point: "+e.getValue()); } set = map.keySet(); System.out.println("Student List: " +set); Collection values = map.values(); it = values.iterator(); int total = 0; while(it.hasNext()) { Integer i = (Integer)it.next(); total += i; } System.out.println("Total point: "+total); System.out.println("Average: "+(float)total/set.size()); System.out.println("Highest Point: "+Collections.max(values)); System.out.println("Highest Point: "+Collections.min(values)); } } Name: VIC, Point: 95 Name: MIN, Point: 77 Name: CHA, Point: 85 Name: KIM, Point: 55 Name: RYU, Point: 65 Student List: [VIC, MIN, CHA, KIM, RYU] Total point: 377 Average: 75.4 Highest Point: 95 Highest Point: 55 //단어카운팅 String[] data = {"A","A","K","A","K","D","D","D","D","Z","C","C","T","T"}; HashMap map = new HashMap(); //map 키 유무 체크후 삽입, 거기에 맞게 value 삽입 //없으면 data의 값이 키로 가고 value=1 로 map에 저장됨 //그다음부터 data값이 중복되면 그 value+1이 됨 for (int i=0; i<data.length; i++) { if(map.containsKey(data[i])) { int value = (int)map.get(data[i]); map.put(data[i], value+1); } else { map.put(data[i], 1); } } Iterator it = map.entrySet().iterator(); while(it.hasNext()) { Map.Entry e = (Map.Entry) it.next(); int value = (int)e.getValue(); System.out.println(e.getKey()+" : "+printBar('*', value)+" "+value); } } public static String printBar(char ch, int value) { char[] bar = new char[value]; for(int i=0; i < bar.length; i++) { bar[i] = ch; System.out.println("bar="+(Arrays.toString(bar))); System.out.println("ch="+ch); } return new String(bar); // String(char[] chArr) } }
4. 제네릭스
- 컴파일시 타입을 체크해주는 기능 -> 자바 특성상 컴파일시에는 형변환을 걸러낼수가없다. 실행은 되나 타입이 안맞으니 ClassCastException을 띄우는 경우가 자주 나오는데 이를 해결 해준다
- 여러종류는 <Object> 라고 쓰고 찾을때 원하는 형태를 넣으면 된다
- 타입체크와 형변환을 생략가능하게 만들므로 코드가 간결해진다.
- 타입을 의미하는 <T> 혹은 엘리멘트를 의미하는 <E>를 많이 쓴다
- 보통 제네릭스를 쓸때에는 타입변수(T,E 등등) 대신 실제 타입을 지정한다
ArrayList<Tv> tvList = new ArrayList<Tv>(); - 제네릭스에도 다형성이 적용 가능하다. 제네릭 타입에 부모가 들어가면 부모와 상속된 모든 자식들을 타입으로 쓸 수 있다
class Student { String name =""; int ban; int no; public Student(String name, int ban, int no) { this.name = name; this.ban = ban; this.no = no; } } public class Ex_1 { public static void main(String[] args) { ArrayList<Student> list = new ArrayList<Student>(); list.add(new Student("Kim", 1, 1)); list.add(new Student("Cha", 1, 3)); list.add(new Student("Vic", 3, 6)); Iterator<Student> it = list.iterator(); while(it.hasNext()) { System.out.println(it.next().name); } } } Kim Cha Vic for (int i=0; i<list.size(); i++) { System.out.println(list.get(i).name+list.get(i).ban+list.get(i).no); } Kim11 Cha13 Vic36 class Student { String name =""; int ban; int no; int kor; public Student(String name, int ban, int no, int kor) { this.name = name; this.ban = ban; this.no = no; this.kor = kor; } @Override public String toString() { return "ban=" + ban + ", no=" + no + ", kor=" + kor; } } public class Ex_1 { public static void main(String[] args) { HashMap<String, Student> map = new HashMap<String, Student>(); map.put("Kim", new Student("Kim", 1, 1, 76)); // System.out.println(map.get("Kim").name+map.get("Kim").ban); Iterator<Map.Entry<String, Student>> it = map.entrySet().iterator(); while(it.hasNext()) { Map.Entry<String, Student> e = (Map.Entry<String, Student>) it.next(); System.out.println(e.getKey()+" "+e.getValue().toString()); } } } Kim ban=1, no=1, kor=76
- 제한된 제네릭도 구현 가능 <T extends A> --> A의 자손만 타입으로 지정 가능
5. 네트워크와 쓰레드
-네트워크 지식 및 네트워크 통신관련은 아래 블로그를 참조!
https://post.naver.com/viewer/postView.naver?volumeNo=7506644&memberNo=30800755&navigationType=push
- 쓰레드는 프로세스와 항상 같이 묶어서 개념을 잡아야한다.
- 프로세스는 실행중인 프로그램이며 자원과 쓰레드로 구성된다.
- 쓰레드는 그 프로그램안에서 실제 작업을 수행하는 일꾼이라고 보면 된다. 모든 프로세스는 최소한 하나의 쓰레드를 가지고 있다. (싱글/멀티 쓰레드로 나뉨)
- 하나의 새 프로세스를 생성하는것보다 하나의 새 쓰레드를 생성하는것이 더 적응 비용이 든다
멀티 쓰레드의 장-단점 - 상속(extends Thread) 하거나 인터페이스(Runnable)을 구현하면 된다.
'자바 기초' 카테고리의 다른 글
자바 기초 03 - 클래스/상속/오버로딩/인터페이스/추상화/SRP-DIP (0) 2021.11.01 자바 기초 01 - 메모리/자바실행원리/일반변수-지역변수 (0) 2021.10.28 자바기초개념 다시잡기 자바의정석 - 연습문제 7장 (0) 2021.07.30 자바기초개념 다시잡기 자바의정석 - 인터페이스/내부클래스/익명클래스 (0) 2021.07.29 자바기초개념 다시잡기 자바의정석 - 상속/캡슐화/다형성/추상화 (0) 2021.07.29