0. 제네릭(Generic)
개요
- 인스턴스 변수에 다른 타입의 변수를 저장하려면 각기 다른 클래스를 저장
- 이러한 불편함을 해소하는 것이 제네릭
학습 목표
- 제네릭 장점
- 제네릭 클래스를 정의 활용
- 제네릭 메서드 정의 활용
제네릭(Generic)이란?
- class Example
- 클래스명 뒤에 라는 타입을 적어서 T를 활용
- 가 들어가면 T에 해당하는 부분을 int로 변환
- Integer는 wrapper class, int는 primitive class
- primitive는 기본 자료형이고 wrapper는 매개변수로 객체를 필요로 할 때 사용
- Character, Integer 제외하고 첫 문자만 대문자로 표현
- 타입을 구체적으로 지정하는 것이 아니라 일반화해두는 것
- 클래스와 메서드에 사용 가능
제네릭 클래스
- 제네릭 클래스
- 제네릭이 사용된 클래스
- class Example{…}
- T를 타입 매개변수
- 여러 개 지정 가능 : class Example <T, K, V>
- T(Type), K(Key), V(Value, E(Element), N(Number), R(Result)
제네릭 클래스를 정의할 때 주의할 점
- 클래스 변수에는 타입 매개변수 사용 불가
- 다른 타입으로 선언되는 경우 같은 변수로 공유가 불가능하기 때문
제네릭 클래스 사용
- wrapper 클래스를 사용
- Exmample example = new Example();
- Exmample example = new Example<>();
- 제네릭 클래스에 다형성 적용 가능
- class Vehicle{ ... }; class Car extends Vehicle{ ...}; class Food{ ... }; class Garage{ private item; public T getItem(){ return item; } public T setItem(T item){ this.item=item; } public static void main(String args[]){ Garage garage = new Garage<>(); garage.setItem(new Car()); // 다형성(polymorphism) garage.setItem(new Food()); //error
제한된 제네릭 클래스
- 타입 매개변수를 선언할 때 특정 클래스 하위 클래스로 지정할 수 있다
- 인터페이스도 가능하다.(선언할 때 똑같이 extends로 사용)
- 특정 클래스와 인터페이스를 동시 적용할 때 extends A & B로 적용
class Vehicle{ ... };
class Car implements Vehicle{ ...};
class SportsCar extends Car implements Vehicle{ ... };
class Garage<T extends Vehicle & Car>{
private <T> item;
public T getItem(){
return item;
}
public T setItem(T item){
this.item=item;
}
public static void main(String args[]){
Garage<Vehicle> garage = new Garage<>();
garage.setItem(new SportsCar()); // 다형성(polymorphism)
garage.setItem(new Car());
제네릭 메서드
- 특정 메서드만 제네릭으로 선언 가능
- 반환 타입 앞에 타입 매개변수 선언으로 사용
- public void full(T amount){ … }
- 클래스 타입 매개변수와 별개
- 같은 T를 사용해도 클래스 제네릭은 클래스가 인스턴스화 될 때, 제네릭 메서드는 메서드 호출될 때 지정
- 메서드 타입 매개변수
- Car.full(50);
- Car.full(50);//생략 가능
- 제네릭 메서드는 메서드를 사용할 때 지정되기 때문에 String 메서드인 length() 같은 것 사용 불가
- 최상위 메서드인 Object 메서드는 사용 가능
와일드카드
- 어떠한 타입으로도 대체 가능한 타입 파라미터
- <? extends T> : T와 T의 하위 클래스를 파라미터로 받기
- <? super T> : T와 T의 상위 클래스를 파라미터로 받기
- <?> : <? extends Object>와 동일, 모든 타입 가능
1. 예외 처리(Exception Handling)
개요
학습 목표
- 예외 처리란
- 컴파일 에러 VS 런타임 에러
- 예외 클래스의 상속 계층
- try-catch문
- throws VS throw
예외 처리란?
예외 처리
- 목적 : 프로그램의 비정상적 종료 방지, 정상 실행 상태 유지
- 에러 발생 원인
- 외부 요인
- 네트워크 문제
- 메모리 부족
- 내부 요인
- 입력 오류
- 코드 에러
- 유효하지 않은 파일
- 외부 요인
- 예제
import java.io.*;
public class Main{
public static void main(String[] args) {
BufferedReader reader = new BufferedReader(new FileReader("not"));
// 존재하지 않은 파일 호출
//빨간 줄로 나옴
//FileNotFoundException
System.out.println(reader.read());
reader.close();
int arr[]={1,2,3,4,5,6};
System.out.println(arr[7]);
//ArrayIndexOutOfBoundsException: Index 7
}
}
컴파일 에러 VS 런타임 에러
컴파일 에러
- 컴파일 에러 : 컴파일할 때 발생하는 에러
- Syntax error : 문법적인 오류
- 자바 컴파일러가 감지 및 공지
런타임 에러
- 런타임 에러 : 코드를 실행할 때 발생하는 에러
- 컴퓨터가 수행할 수 없는 작업 요청할 때 발생
- JVM(자바 가상 머신)으로 감지
에러와 예외
- 에러 : 한번 실행하면 복구하기 어려운 수준의 오류( 스택오버플로우, 메모리 부족)
- 예외 : 상대적으로 수습 가능한
예외 클래스 상속 계층
예외 클래스 계층
- java.lang → Object → Throwable → Error /Exceptions
일반 예외 클래스
- RuntimeException 클래스 및 하위 클래스를 제외한 Exception 클래스
- 컴파일러가 확인한다고 하여 checked exception이라 부름
- 사용자 편의 실수로 주로 발생
- ClassNotFoundException, DataFormatException
실행 예외 클래스
- 실행 시 발생하는 RuntimeException
- 컴파일러가 예외 처리 코드 검사를 하지 않아 unchecked exception이라 부름
- ClassCastException, ArrayIndexOutOfBoundsException, NullPointerException
try - catch 문
- try{…}
- 예외가 발생할 수 있는 코드
- catch(Exception e){…}
- 해당 예외가 발생할 경우 처리할 코드
- Exception 클래스는 모든 클래스를 받는다
- 여러 catch문을 작성하여 해당 예외에 대한 처리 가능
- finally{…}
- 예외와 상관없이 실행
- 예제
public class Main{
public static void main(String[] args) {
System.out.println("start program");
try{
printlen(null);
}
catch(ArrayIndexOutOfBoundsException e){
System.out.println("ArrayIndexOutOfBoundsException");
}
catch(NullPointerException e){
System.out.println(e.getMessage()); // null 출력
System.out.println(e.toString()); // java.lang.NullPointerException 출력
e.printStackTrace();
//java.lang.NullPointerException
//at Main.printlen(Main.java:21)
//at Main.main(Main.java:6) 출력
}
finally{
System.out.println("end program");
}
}
static void printlen(String str){
System.out.println("strlen = " + str.length());
}
}
- 에러 정보
- .getMessage() : 에러 원인 간단히 출력
- .toString() : 에러 내용과 원인 출력
- .printStackTrace() : 에러 발생 근원지에서 단계별로 에러 출력
에러 전가
throws()
- 메서드 내에 발생할 수 있는 예외를 상위(호출하는 쪽)에 전가하는 것
- main 메서드 뒤에 선언이 가능하고 이 경우 JVM이 콘솔에 출력하여 처리
- 선언
- void method() throws Exception { … }
throw
- 예외를 의도적으로 발생
- 사용 : throw Exception
- 예제
public class Main{
public static void main(String[] args) {
try{
printlen(null);
}
catch(NullPointerException e){
System.out.println(e.toString());
}
}
static void printlen throws NullPointerException(String str){
try {
System.out.println("strlen = " + str.length());
}
catch (NullPointerException e){
throw e; // 예외 강제 발생
}
}
}
2. 컬렉션 프레임워크(Collection Framework)
개요
- 학습 목표
- 컬렉션 프레임워크의 핵심 인터페이스 이해
- 주요 인터페이스, 컬렉션 클래스의 메서드 사용
- 상황에 적합한 인터페이스와 컬렉션 클래스 판단
컬렉션 프레임워크란?
- 컬렉션 프레임워크
- 컬렉션 : 여러 데이터들의 집합
- 컬렉션 프레임워크 : 컬렉션을 다루기 위한 메서드 집합
- 특정 자료구조에 데이터 추가, 삭제, 수정, 검색에 대한 메서드 제공
컬렉션 프레임워크의 구조
- 컬렉션 프레임워크의 주요 인터페이스
- List : 데이터 순서 유지, 중복 저장 가능
- ArrayList, Vector, Stack, LinkedList
- Set : 데이터 순서 유지 안됨, 중복 저장 불가
- HashSet, TreeSet
- Map : key와 value 쌍으로 데이터 저장
- HashMap, HashTable, TreeMap, Properties
- List : 데이터 순서 유지, 중복 저장 가능
- List와 Set은 공통점이 많아 Collection이라는 인터페이스에 묶인다
Collection 인터페이스
List
- List
- 배열과 같이 객체를 일렬로 놓은 구조
- 객체를 저장하면 자동으로 인덱스 부여
- 인덱스를 활용하여 객체 추가, 검색, 삭제 가능
- List 인터페이스의 공통 메서드
ArrayList
- List 인터페이스로 구현
- 연속적으로 데이터 저장
- Vector와 유사하지만 개선됨
- 객체를 추가하면 자동으로 용량 늘어남
List<Integer> num1 =new ArrayList<Integer>();
//초기 용량은 10
List<Integer> num2 =new ArrayList<Integer>(30);
//저장 용량 30으로 설정
- 객체를 삭제하게 되면 해당 객체 이후를 1씩 당긴다
- 빈번한 삽입과 삭제의 경우 LinkedList가 효율적
LinkedList
- List 인터페이스로 구현
- 불연속적으로 데이터 저장
- 서로 연결됨
- node에 값이 있고 이전 객체 주소 값, 이후 객체 주소 값이 존재
- 삭제할 때 이전 객체의 연결을 변경(ArrayList보다 효율적)
ArrayList와 LinkedList 차이
- ArrayList
- 중간에 존재하는 객체 추가 및 삭제할 경우 데이터 이동이 크게 일어남
- 특정 인덱스의 객체 주소 값을 찾는 검색에서는 유리
- LinkedList
- 중간에 존재하는 객체 추가 및 삭제할 경우 주소 값만 변경한다
- 특정 인덱스의 객체 주소 값을 찾으려면 순차적으로 접근해야 해서 불리
Iterator
Iterator
- 컬렉션에 저장되어 있는 요소를 순차적으로 읽는 것
- Collection 인터페이스에, iterator 인스턴스를 반환하도록 구현한 iterator() 메서드로 활용
- List, Set은 Collection 인터페이스에서 구현하였기 때문에 사용 가능
- 사용 메서드
출처 : UrClass
- 활용
List<Integer> list=new ArrayList();
Iterator<Integer> iterator = list.iterator();
While(iterator.hasNext()){
int num=iterator.next();
iterator.remove(); // next로 가져온 객체 삭제
}
Set
Set
- 중복된 값 허용하지 않고 저장 순서가 상관없는 컬렉션 클래스
- Set 공통 메서드
HashSet
- Set 인터페이스를 구현한 컬렉션 클래스
- 중복 값 허용하지 않고, 순서 상관없다
- hashCode() 메서드를 사용해 해쉬 코드를 가져오고
- 기존에 있는 객체와 같으면 add()에 false 반환
- 기존에 있는 객체와 다르면 add()에 true 반환 후 추가
- 활용
HashSet<Integer> nums=new HashSet<Integer>();
nums.add(1);
nums.add(2);
nums.add(3);
nums.add(4);
nums.add(1); // 중복
Iterator it=nums.iterator();
while(it.hasNext()){
System.out.println(it.next()); //1,2,3,4 출력
}
TreeSet
- 중복 저장 허용하지 않고, 저장 순서 무관
- 이진 탐색 트리(Binary search tree) 형태
- 하나의 부모 노드에 최대 두 개의 자식 노드로 이루어진 이진트리의 일종
- 왼쪽 노드에는 부모 노드보다 같거나 작은 값, 오른쪽 노드에는 같거나 큰 값
- 최상단의 노드가 root 노드
TreeSet<Integer> nums = new TreeSet<>();
nums.add(1);
nums.add(2);
nums.add(3);
nums.add(4);
nums.add(1);
System.out.println(nums); // 오름차순으로 출력
System.out.println(nums.higher(3)); //3보다 큰 가장 작은 수 4 출력
System.out.println(nums.first()); // 최솟값 출력
System.out.println(nums.last());//최댓값 출력
System.out.println(nums.subset(1,3); //1-3까지 수 출력
Map<key, value>
Map
- 키와 값으로 구성된 객체를 저장하는 구조
- 객체를 Entry 객체라고 부른다
- key, value 모두 객체로 저장
- key는 중복되지 못하지만 value는 중복 가능
- Map 인터페이스 공통 메서드
HashMap
- 키와 값으로 저장 위치 결정
- 삽입 순서, 위치 무관
- 해싱 사용
- 많은 양의 데이터 효율적으로 처리
- 활용
import java.util.*;
class HashMap{
public static void main(String[] args){
HashMap<String, Integer> hmap=new HashMap<>();
map.put("banana", 1200);
map.put("apple", 1500);
map.put("pineapple", 5000);
map.put("melon", 9000);
map.remove("melon");
System.out.println("entry 수: ", hmap.size());
System.out.println("banana price : ", hmap.get("banana"));
Set<String> keySet = hmap.keySet();
Iterator<String> it = keySet.iterator();
while(it.hasNext()){
String key=it.next();
System.out.println(key + " " + hmap.get(key)); // 키와 값을 모두 출력
}
Set<Map.Entry<String, Integer>> entrySet =hmap.entrySet();
Iterator<Map.Entry<String, Integer>> it2=entrySet.iterator();
while(it2.hasNext()){
System.out.println(it2.getKey() + " " +it2.getValue());
}
}
}
HashTable
- HashMap의 이전 버전
- HashMap과 구조가 동일하고 사용 방법 유사
컬렉션 클래스의 정리
- 키, 값 쌍?
- yes - 순서가 중요하지 않으면 HashMap, 중요하면 LinkedHashMap, 정렬이 필요하면 TreeMap
- No
- 객체 중복 허용 X : 순서가 중요하지 않으면 HashSet, 중요하면 LinkedHashSet, 정렬이 필요하면 TreeSet
- 객체중복 허용
- 첫 요소나 마지막 요소 접근? 리스트의 크기가 큰가? 객체를 빈번히 삭제/수정하나? ->LinkedList
- 그렇지 않은 경우 -> ArrayList
'Backend boot camp > Session1' 카테고리의 다른 글
[JAVA] 심화 - Thread, JVM (1) | 2022.09.19 |
---|---|
[JAVA] 심화(Effective) (0) | 2022.09.14 |
[JAVA] 객체 지향 프로그래밍 심화 (0) | 2022.09.06 |
[JAVA] 객체 지향 프로그래밍 기초 (0) | 2022.09.06 |
[JAVA] 기초 - 배열 (0) | 2022.09.06 |