본문 바로가기

Language/Java

Java의 정석 정리 3

프로그램 오류

컴파일 에러 - 컴파일할 때 발생하는 에러

런타임 에러 - 실행할 때 발생하는 에러

논리적 에러 - 의도와 다르게 동작(실행 시)

 

Java의 런타임 에러

에러(error) - 프로그램 코드에 의해서 수습될 수 없는 심각한 오류

예외(exception) - 프로그램 코드에 의해서 수습될 수 있는 다소 미약한 오류

 

예외처리(exception handling)

정의 - 프로그램 실행 시 발생할 수 있는 예외의 발생에 대비한 코드를 작성하는 것

목적 - 프로그램의 비정상 종료를 막고, 정상적인 실행상태를 유지하는 것

 

예외 클래스 계층구조

RuntimeException Classes - 프로그래머의 실수로 발생하는 예외 <- 예외처리 선택

Exception Classes - 사용자의 실수와 같은 외적인 요인에 의해 발생하는 예외 <- 예외처리 필수

출처 :&nbsp;https://www.scientecheasy.com/2020/08/exception-hierarchy-in-java.html/

Catch 블럭

-try블럭에서 예외가 발생하면, 발생한 예외를 처리할 catch블럭을 찾는다.

-첫번째 catch블럭부터 순서대로 찾아 내려가며, 일치하는 catch블럭이 없으면 예외는 처리되지 않는다.

-예외의 최고 조상인 Exception을 처리하는 catch블럭은 모든 종류의 예외를 처리할 수 있다.(때문에 반드시 마지막 catch블럭이어야 한다)

-발생한 예외 객체를 catch블럭의 참조변수로 접근할 수 있다.

 

Finally 블럭

-예외의 발생여부와 관계없이 실행되어야 하는 코드를 넣는다.

-선택적으로 사용할 수 있으며, try-catch-finally의 순서로 구성

-예외 발생시, try -> catch -> finally의 순서 미 발생시, try -> finally의 순서로 실행

-try 또는 catch블럭에서 return문을 만나도 finally블럭은 수행된다.

 

메서드에 예외 선언하기

-예외를 처리하는 또 다른 방법

-사실은 호출한 메서드로 전달해주는 것

-호출한 메서드에서 예외처리를 해야만 할 때 사용

void method() throws Exception1, Exception2, ... ExceptionN (\{
    //메서드 내용
}

 

연결된 예외(chained exception)

-예외 A가 예외 B를 발생시켰다면, A를 B의 '원인 예외'라고 한다.

Throwable initCause(Throwable cause)  // 지정한 예외를 원인 예외로 등록
Throwable getCause()                  // 원인 예외를 반환


try{
    startInstall();         // SpaceException 발생
    copyFiles();
} catch (SpaceException e) {
    InstallException ie = new InstallException("설치중 예외발생");  // 예외 발생
    ie.initCause(e); // InstallException의 원인 예외를 SpaceException으로 지정
    throw ie;        // InstallException을 발생시킨다.
} catch (MemoryException me) {
    ...

 

이유

-여러 예외를 큰 분류의 예외로 묶을 때, 연결된 예외로 처리

*상속으로 처리하면, 상속관계도 변경해야 하고 실제로 발생한 예외를 알 수 없다는 단점이 있음

-필수 예외(Exception자손)를 선택 예외(RuntimeException)으로 바꿀 때

 

컬렉션 프레임웍(collections framework)

컬랙션(collection) - 여러 객체(데이터)를 모아 놓은 것을 의미

프레임웍(framework) - 표준화, 정형화된 체계적인 프로그래밍 방식

 

-컬렉션(다수의 객체)을 다루기 위한 표준화된 프로그래밍 방식

-컬렉션을 쉽고 편리하게 다룰 수 있는 다양한 클래스를 제공

-java.util패키지에 포함. JDK1.2부터 제공

 

컬렉션 클래스 - 다수의 데이터를 저장할 수 있는 클래스(ex, Vectior, ArrayList, HashSet)

 

핵심 인터페이스

https://www.geeksforgeeks.org/how-to-learn-java-collections-a-complete-guide/

 

List - 순서가 있는 데이터의 집합. 데이터의 중복을 허용 ex) ArraryList, LinkedList, Stack, Vector, ... etc

set - 순서를 유지하지 않는 데이터의 집합. 데이터의 중복 불가 ex) HashSet, TreeSet, ... etc

Map - 키(key)와 값(value)의 쌍(pair)으로 이루어진 데이터의 집합. 순서는 유지되지 않으며, 키는 중복을 허용하지 않고, 값은 중복을 허용 ex) HashMap, TreeMap, Hashtable, Properties, ... etc

 

ArrayList 삭제 과정

출처 : Java의 정석

1. 삭제할 데이터 아래의 데이터를 한 칸씩 위로 복사해서 삭제할 데이터를 덮어쓴다.

2. 데이터가 모두 한 칸씩 이동했으므로 마지막 데이터는 null로 변경한다.

3. 데이터가 삭제되어 데이터의 개수가 줄었으므로 size의 값을 감소시킨다.

위 방식으로 인해 첫 번째 객체부터 삭제하는 경우 배열 복사가 발생하고 마지막 객체부터 삭제하는 경우에는 배열 복사가 없다.

 

Enumeration, Iterator, ListIterator

-컬렉션에 저장된 데이터를 접근하는데 사용되는 인터페이스

-Enumeration은 Iterator의 구버젼

-ListIterator는 Iterator의 접근성을 향상시킨 것(단방향 -> 양방향)

 

지네릭스(Generics)

-컴파일시 타입을 체크해 주는 기능

-객체의 타입 안정성을 높이고 형변환의 번거로움을 줄임(하나의 컬렉션에는 대부분 한 종류의 객체만 저장)

-타입 안정성을 제공하고 타입체크와 형변환 생략으로 코드가 간결해 진다.

 

class Box<T> {    // 지네릭 타입 T를 선언
    T item;
    
    void setItem(T item) { this.item = item; }
    T getItem() { return item; }
}

-static 멤버에는 타입 변수 T를 사용할 수 없다.

 

-지네릭 타입의 배열 T[]를 생성하는 것은 허용되지 않는다.

class Box<T> {
    T[] itemArr;  // 가능. T타입의 배열을 위한 참조변수
        ...
    T[] toArray() {
        T[] temArr = new T[itemArr.length];  // 에러. 지네릭 배열 생성불가
        ...
        return tmpArr;
    }
        ...
}

 

-지네릭 타입에 'extends' 를 사용하면, 특정 타입의 자손들만 대입할 수 있게 제한할 수 있다.

class FruitBox<T extends Fruit> {
    ...
}

-인터페이스의 경우에도 'implements' 가 아닌, 'extends'를 사용

 

와일드 카드 '?'

-지네릭 타입에 와일드 카드를 쓰면, 여러 타입을 대입가능. 단, 와일드 카드에는 <? extends T & E>와 같이 '&' 를 사용불가

<? extends T>  와일드 카드의 상항 제한. T와 그 자손들만 가능

<? super T>      와일드 카드의 하한 제한. T와 그 조상들만 가능

<?>                    제한없음. 모든 타입이 가능. <? extends Object>와 동일

 

지네릭 메서드

-반환타입 앞에 지네릭 타입이 선언된 메서드

static <T> void sort(List<T> list, Comparator<? super T> c)

 

-클래스의 타입 매개변수<T>와 메서드의 타입 매개변수 <T>는 별개

class FruitBox<T> {
        ...
    static <T> void sort(List<T> list, Comparator<? super T> c) {
        ...
    }
}

 

-지네릭 메서드를 호출할 때, 타입 변수에 타입을 대입해야함(대부분 추정이 가능하므로 생략할 수 있음)

FruitBox<Fruit> fruitBox = new FruitBox<Fruit>();
FruitBox<Fruit> appleBox = new FruitBox<Apple>();
      ...
System.out.println(Juicer.<Fruit>makeJuice(fruitBox);
System.out.println(Juicer.makeJuice(appleBox);

 

형변환

-지네릭 타입과 원시 타입간의 형변환은 불가능

Box            box = null;
Box<Object> objBox = null;

box    = (Box)objBox;      // 가능. 지네릭 타입 -> 원시 타입. 경고 발생
objBox = (Box<Object>)box; // 가능. 원시 타입 -> 지네릭 타입. 경고 발생

 

'Language > Java' 카테고리의 다른 글

Java의 정석 정리 4  (1) 2023.09.18
Java의 정석 정리 2  (0) 2023.09.10
Java의 정석 정리  (0) 2023.09.07
강의 내용 정리 2  (0) 2023.03.08
강의 내용 정리 1  (0) 2023.03.04