본문 바로가기
Study/Java

07. <예외처리,equals, hashCode, clone, toString> ~자바의 정석 summary ~

by 하구땡 2023. 1. 14.
반응형

31. 예외처리

(1) 컴파일 에러 : 컴파일 시에 발생하는 에러

(2) 런타임 에러 : 실행 시에 발생하는 에러

           (2.1)에러(error) : 프로그램 코드에 의해서 수습될 수 없는 오류

           (2.2)예외(exception) : 프로그램 코드에 의해서 수습될 수 있는 오류

              (2.2.1)Exception과 그 자손들(checked예외)

                       - 예외 필수처리(try-catch), 클래스 이름에 선언

                      - 사용자의 실수와 같은 외적인 요인에 의해 발생

IOexception (입출력이 잘못되었을 때)
ClassNotFoundException(클래스의 이름을 잘못적었을 때)
FileNotFoundException(존재하지 않는 파일의 이름을 입력했을 때)
DataFormatException(데이터 형식이 잘못됐을 때)

              (2.2.2)RuntimeException과 그 자손들(unchecked예외)

                - 예외 선택처리, 클래스 이름에서 선언하지 않음

                      - 프로그래머의 실수로 발생하는 예외

ArrayIndexOutOfBoundsException(배열의 범위를 벗어남)
NullPointerException(값이 Null인 참조변수의 멤버를 호출)
ClassCastException(클래스간의 잘못된 형변환)
ArithmeticException(정수를 0으로 나누려고 했을 때)

 

(3) 논리적 에러 : 실행은 되지만, 의도와 다르게 동작하는 것

 

32. 예외처리(exception handling)

- 예외의 경우 프로그래머가 이에 대한 처리를 미리 해주어야 한다.

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

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

*예외를 처리하지 못할 경우 프로그램은 비정상적으로 종료되며 이러한 예외는

 JVM의 ‘예외처리기’가 받아서 예외의 원인을 화면에 출력한다.

*예외를 처리하기 위해 try-catch문 사용

try {
   // 예외가 발생할 가능성이 있는 문장들 삽입
} catch (Exception e1) {
   // Exception1이 발생했을 경우, 이를 처리하기 위한 문장 삽입
] catch (Exception e2) {
   // Exception2가 발생했을 경우, 이를 처리하기 위한 문장 삽입
} finally {
   // 예외의 발생여부와 관계없이 항상 수행되어야 하는 문장 삽입
}

 1) 하나 이상의 catch블럭이 올 수 있으며, 발생한 예외의 종류와 일치하는

    단 한개의 catch블럭만이 수행된다.

 2) if문과 달리, try블럭이나 catch블럭 내에 포함된 문장은 괄호를 생략 불가

 3) n개 이상의 catch블럭 생성시 조상클래스의 예외 참조변수를 하단으로 

    배치한다.

 

           32-1. 멀티 catch블럭

- 여러 catch블럭을 ‘|’기호를 사용해 하나의 catch블럭으로 합치는 것

- 연결할 수 있는 예외 클래스의 개수에는 제한이 없다.

- 이때, |로 연결된 클래스가 조상과 자손 관계에 있다면 컴파일 에러가

  발생하므로 불가하다.

- 멀티catch블럭은 참조변수로 두 클래스간의 공통된 메서드만 호출 가능

- try-catch블럭으로 처리되지 못한 예외는 종료된다.

 

           32-2. 예외 인스턴스 발생

[1] 예외 발생시 catch블럭의 괄호에 선언된 참조변수를 통해 예외 인스턴스에

    접근할 수 있다. 

[2] printStackTrace() : 예외발생 당시의 호출스택에 있었던 메서드의 정보와

                                 예외메시지를 화면에 출력한다.

[3] getMessage() : 발생한 예외클래스의 인스턴스에 저장된 메시지를 얻는다.

 

           32-3. 예외 발생시키기

- 키워드 throw를 사용해 프로그래머가 고의로 예외를 발생시킨다.

[1] 연산자 new를 이요해 발생시키려는 예외 클래스의 객체 생성          

Exception e = new Exception(”고의로 발생시켰음”);

[2] 키워드 throw를 이용해 예외를 발생시킨다.

           throw e;

           (=throw new Exception(”고의로 발생시켰음”))

 

           32-4. 메서드에 예외 선언하기

- 메서드의 선언부에 키워드 throw를 사용해서 메서드 내에서 발생할 수 있는

  예외를 적어준다.

- 예외가 여러개일 때는 쉼표로 구분한다.

* 예외를 발생시키는 키워드 : throw

* 예외를 선언하는 키워드 : throws

- 메서드에 예외를 선언해주면 체크드 예외를 try-catch문으로 처리해주지

  않아도 컴파일 에러가 발생하지 않는다.

 

           32-5. 연결된 예외(chained exception)

- 하나의 예외를 다른 예외의 원인 예외로 포함시켜 처리해주는 것

- 여러 가지 예외를 하나의 큰 분류의 예외로 묶어서 다루기 위함

- checked예외를 unchecked예외로 바꾼다.

[1] Throwable initCause(Throwable cause)

 : 지정한 예외를 원인 예외로 등록

[2] Throwable getCause()

 : 원인 예외를 반환

 

33. Object클래스

- 모든 클래스의 최고 조상이므로 모든 클래스에서 Object클래스의 멤버들을

  바로 사용할 수 있다.

- 멤버변수없이 오직 11개의 메서드만 가지고 있다.

protect object clone() 객체 자신의 복사본 반환
boolean equals(Object obj) 자신과 Obj가 같은 객체인지 알려준다. (true/false로 반환)
protected void finalize() 거의 사용안함
Class getClass() 자신의 클래스 정보를 담고 있는 Class인스턴스를 반환
int hashCode() 자신의 해시코드를 반환
String toString() 자신의 정보를 문자열로 반환
void notify() 자신을 사용하려고 기다리는 쓰레드를 하나만 깨운다.
void notifyAll() 자신을 사용하려고 기다리는 모든 쓰레드를 깨운다.
void wait()
void wait(long timeout)
void wait(long timeout, int nanos)
다른 쓰레드가 notify()나 notifyAll()을 호출할 때까지 현재 쓰레드를 무한히 또는 지정된 시간동안 기다리게 한다.
timeout-천 분의 1초
nanos-109분의 1초

 

[1] equals()

: 매개변수로 객체의 참조변수를 받아 비교해 결과를 boolean값으로 알려준다.

  -> 따라서 서로 다른 두 객체를 해당 메서드로 비교하면 항상 false이다.

  -> 객체가 가진 인스턴스값을 비교하고 싶다면 오버라이딩 해야한다.

public static void main(String[] args) {
           Value v1 = new Value(10);
Value v2 = new Value(10);
}
class Value {
           int value;
 
           Value(int value) {
this.value = value;
}
}
  => v1과 v2는 서로 다른 객체이므로 equals값이 false로 반환된다.
public static void main(String[] args) {
           Value v1 = new Value(10);
Value v2 = new Value(10);
}
class Value {
           int value;
 
           public boolean equals(Object obj) {
           if(obj instanceof Value)
                      return value ==((Value)obj).value;
           else
                      return false
}
 
           Value(int value) {
this.value = value;
}
}
  => 해당과 같이 오버라이딩 해야한다. (반환값: true)

->String클래스는 문자열의 내용을 비교하도록 오버라이딩 되어있다.

 

[2] hashCode()

: 해싱기법에 사용되는 해시함수를 구현한 것으로, 해싱은 데이터관리기법 중 하나인데 다량의 데이터를 저장하고 검색하는 데 유용하다.

- 해시함수는 찾고자하는 값을 입력하면, 그 값이 저장된 위치를 알려주는 해시코드를 반환한다.

- 인스턴스 변수값으로 객체의 같고 다름을 판단하는 경우, equals메서드 뿐만 아니라 hashCode메서드도 오버라이딩해줘야 한다.

- String클래스는 문자열의 내용이 같으면 동일한 해시코드를 반환하도록 자동 오버라이딩 되어 있다.

- System.identityHashCode(Object x) : 항상 다른 해시코드값 반환

 

[3]toString()

: 인스턴스에 대한 정보를 문자열로 제공할 목적으로 정의한다.

-> 그러나 오버라이딩 하지 않으면 참조형의 경우 주소값이 반환되므로 인스턴스의 내용을 반환하고 싶다면 마찬가지로 오버라이딩해야 한다.

->public String toString() {}

->Object클래스에서 toString()의 접근자가 public이므로 오버라이딩을 할 때도 동일하게 public으로 한다.

 

[4]clone()

: 자신을 복제하여 새로운 인스턴스를 생성하는 일을 한다.

-> 원래의 인스턴스는 보존하고 clone메서드를 이용해서 새로운 인스턴스를 생성해 작업을 할 경우 작업이전의 값이 보존되므로 원래의 상태로 되돌리거나 / 변경되기 전의 값을 참고하는데 도움이 된다.

-> 참조 타입의 인스턴스 변수가 있는 경우 완전한 인스턴스 복제가 이루어지지 않으므로 clone메서드를 오버라이딩해서 사용해야 한다.

-> Cloneable 인터페이스를 구현한 클래스에서만 clone()을 호출할 수 있다.

구현을 해줄 때에는 접근 제어자를 public으로 변경해주어야 한다.

-> clone메서드는 반드시 예외처리 해주어야 한다. (CloneNotSupportedException 예외)

-> 배열의 경우 Object클래스를 상속받으며, 동시에 Cloneable인터페이스, Serializable인터페이스가 구현되어 있다. 또한, clone()이 public으로 오버라이딩 되어있고 원본과 같은 타입을 반환하므로 형변환이 따로 필요하지 않다.

  =>System.arraycopy()를 통해 복사할 수도 있지만, clone()으로도 복사할 수 있다.

반응형

댓글