티스토리 뷰

Java/Java Study 기록 일지

JSON 백엔드 자바 6회차

응애~ 개발자 2023. 2. 21. 00:03
728x90
반응형

예외 처리

 이번 회차에서는 예외처리에 대해서 공부할것인데 간단하게 정리하고 자세한것은 추후에 따로 설명할 예정이다.

 예외 처리를 공부하기 전에 알아야 될 오류가 3가지 사항이다.

  • 컴파일 에러 : 컴파일 시 발생하는 에러
  • 런타임 에러: 실행시 발생하는 에러
  • 논리적 에러: 실행하는데는 문제 없지만 의도와 다르게 동작하는 경우

컴파일 에러는 소스코드 잘못 작성시 오류가 나서 만야게 소스코드가 이상있으면 바로 에러 나기 때문에 바로 수정하면 된다. 하지만 런타임 에러같은 경우는 코드상 오류나지는 않지만 프로그램상 비정상적으로 작동 할때 오류나기 때문에 바로 수정하기가 힘들뿐만 아니라 찾는데도 시간이 걸리기 때문이다 예를 들어 n/ 0은 계산할 경우 자바 문법상 오류는 아니지만 실제로 계산이 불가능 하기 때문에 에러가 나는 경우이다. 마지막으로 논리적 에러는 자바 소스코드또는 실행 하는 도중 오류나야 될 상황이 아닌데 의도적으로 실행이 되지 않은 경우이다. 예를 들어 치킨을 시켰는데 피자가 올경우에는 프로그램상 오류는 아니지만 사용자한테 제공하는 데이터상으로는 오류이다.

 

Exception Class

 모든 예외의 가장 위 조장은 Exception Class이다. 어떤 오류든 간에 Exception Class바탕으로 이루어 져있는데 Exception Class에서는 두가지 분류로 나온다. RuntimeException 과 그 외로 보면 된다. RuntimeExcption은 개발자가 코드를 잘못 작성했을때 나타내는 오류이고 그 외의 오류는 외부의 환경에서 나온 오류라고 보면 된다.

 

예외 처리하기위한 문법

 코드상 논리적으로 예외 처리할 경우가 3가지 방법이 있다 . 우선 try-catch문 부터 볼 예정이다.

try{
	// 실행할 코드
}catch(Exception e1){
	// 예외 1상황
}catch(Exception e2){
	// 예외 2상황
}catch(Exception e3){
	// 예외 3상황
}finally{
	// try 구문안에서 예외가 발생여부와 상관없이 실행 되어야 할 코드
}

 문법은 위처럼 작성해야 한다. 다만 주의점은 catch 구문 작성할때  논리적 에러상 우선순위가 높은것은 부터 맨 위에 작성하는것이 좋다. 맨위에 Exception을 사용하고 나머지는 Exceoption 자손의 클래스를 사용할경우 Exception만 실행 되고 나머지는 실행이 되지 않을것이다. finally는 필수로 작성하지 않아도 된다.

 그 다음 볼것은 고의로 예외를 발생할 경우이다.

public static void main(String[] args) {
    throw new RuntimeException("강제로 에러 시키기");
}

 강제로 오류 시켜야 할경우가 있다. 위에 언급했듯이 논리적 에러가 해당되는 경우이다. 만약 잘못된 주문 정보가 오면 실행하는데는 문제가 없지만 사용자입장에서는 문제가 생기기 때문에 강제로 오류를 만들고 다시 정상적인 주문 정보가 작성되도록 해야하기 때문이다. 문법은 간단하다. throw new 예외클래스(에러메세지) 이런식으로 작성하면 끝이다.

그 다음 볼것은 메소드 예외 선언하기다.

public static void main(String[] args) throws IOException {
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
}

 try - catch 문으로 작성하는것도 코드가 길고 예외상황을 고려해서 작성 해야 하지만 메소드에 throws를 사용하면 예외상황을 고려할필요가 없어서 코드 내에서 예외 상황을 대비하기가 쉬울 뿐만 아니라 메소드에 throws 옆에 클래스만 추가만 해주기 때문에 개발하는데 조금이나마 불편한점을 해소시켜 줄수가 있다.

Call by Value vs Call by Reference

 어떤 프로그램언어이든 이 부분을 빠질수가 없다. 간단 하게 설명한다면 Call by Value는 값에 의한 호출이라고 하고 값에 의한 호출은 임시 메모리에  저장해서 처리하는 방식이라면 Call by Reference는 주소값 참조해서 처리하는 방식이다. 자바에서는 주소값대신 ID라고 쓰지만 실제 메모리에는 주소로 저장한다. 참고로 자바는 Call by Value 언어이다. 자세한것은 따로 글로 올릴 예정이다.

Call by Value

이미지를 보면 a,b를 저장하고 값을 바꾸는 메소드 호출했는데도 바뀌지 않았다. 그 이유는 main 안에 a, b와 changeValue의 a, b가 저장하는 메모리 주소가 달라서 저런 형상이 생긴것다. 변수명은 같아도 저장하는 주소가 다르기 때문에 changeValue를 메소드 호출해도 값이 변경이 안된다.

 

Call by Reference

 이번에는 Call By Reference 값의 의한 참조이다. 자바는 Call By Value 언어이지만  클래스가 생성되면 Heap 메모리에 생성이된다.  Heap메모리안에 데이터 값은 Stack 메모리를 참조하는 식으로 저장한다. 일단 this를 사용하면 자기 자신 객체 주소를 참조해서 데이터 처리하기 때문에 값이 change_value를 사용하면 값이 바뀌어 진다.

 

연습문제

Money.java

public class Money {

  private int value;

  public Money(int value) {
    this.value = value;
  }
}

Main.java

public class Main {

  public static void main(String[] args) {
    Money money1 = new Money(500);
    Money money2 = new Money(500);
    System.out.println(money1 == money2);
    System.out.println(money1.equals(money2));
  }
}

false, false를 false, true로 변경해라

 

문제 풀이

 Object 최상의 클래스에서는 equals를 제공한다. equals 메소드 오버라이딩으로 아래 처럼 재정의 하면된다.

Money.java

public class Money {

  private int value;

  public Money(int value) {
    this.value = value;
  }

  @Override
  public boolean equals(Object obj) {
    Money money2 = (Money) obj;
    return value == money2.value;
  }
}

연습문제

문자 말고 숫자만 입력하라구!

위 코드를 수정해서 아래와 같이 작동되도록 만들어라.

public class Main {

  public static void main(String[] args) {
    Scanner scanner = new Scanner(System.in);

		boolean isContinued = true;
		while (isContinued) {
            System.out.println("숫자를 입력해주세요.");
            String input = scanner.nextLine();
			int number = parseInt(input);
			System.out.println("입력하신 숫자는 " + number + "입니다.");
		}
  }
}
숫자를 입력해주세요.
123
입력하신 숫자는 123입니다.
숫자를 입력해주세요.
abcd
잘못된 값을 입력하셨습니다.
숫자를 입력해주세요.
1234
입력하신 숫자는 1234입니다.
숫자를 입력해주세요.
  • try-catch를 활용해라.
  • 잘못된 값(숫자가 아닌 값)을 입력했을 때, Exception이 발생하면서 프로그램이 종료되면 안 된다.

문제 풀이

  문자열에서 숫자 변경시에서 예외처리 하면된다. 그리고 NumberFormatException 예외처리하면 NumberFormatException은 문자열에서 숫자 변경시 숫자외 문자열 입력시 나타내는 오류이다. 그리고 catch문에서 continue를 쓰면 바로 종료 되지 않고도 while문안에서 처리가 가능하다.

Code

import java.util.Scanner;

public class Main {

  public static void main(String[] args) {
    Scanner scanner = new Scanner(System.in);

    boolean isContinued = true;
    while (isContinued) {
      System.out.println("숫자를 입력해주세요.");
      String input = scanner.nextLine();
      try {
        int number = Integer.parseInt(input);
        System.out.println("입력하신 숫자는 " + number + "입니다.");
      } catch (NumberFormatException e) {
        // 입력 잘못 할시 continue로 
        System.out.println("잘못된 값을 입력하셨습니다.");
        continue;
      }
    }
  }
}

휴대폰 번호 입력받기

 이번 문제는 설명 따로 안하겠다. 위에 내용 다 공부했으면 밑에 코드만 보면 이해가 될것이다.

요구사항 1

public class PhoneNumber {

  private String number01, number02, number03;

  public PhoneNumber(String phoneNumber) {
    if (phoneNumber.substring(0, 3).equals("010")) {
      number01 = phoneNumber.substring(0, 3);
    } else {
      throw new IllegalArgumentException("휴대폰 번호는 010으로 시작해야 합니다.");
    }

    if (phoneNumber.length() == 11) {
      number02 = phoneNumber.substring(3, 7);
      number03 = phoneNumber.substring(7, 11);
    } else {
      throw new IllegalArgumentException("휴대폰 번호는 11글자여야 합니다.");
    }
  }

  public String getPhoneNumberFormally() {
    return number01 + "-" + number02 + "-" + number03;
  }
}

요구사항 2

main만 수정하면된다.  try-catch문으로 감싸고 에러가 나오면 getMessage를 사용하면된다. 그리고 정상입력될때 까지 반복해야 하기 때문에 catch문끝에 continue만 추가하면된다.

import java.util.Scanner;

public class Main {

  public static void main(String[] args) {
    Scanner scanner = new Scanner(System.in);

    while (true) {
      try {
        System.out.println("휴대폰 번호를 입력해주세요. ");
        String input = scanner.nextLine();
        PhoneNumber phoneNumber = new PhoneNumber(input);
        System.out.println(
            "휴대폰 번호를 정상적으로 입력하셨습니다. 입력하신 휴대폰 번호는 " + phoneNumber.getPhoneNumberFormally() + "입니다.");
        break;
      } catch (IllegalArgumentException e) {
        System.out.println(e.getMessage());
        continue;
      }
    }
  }
}

동일성(identity) VS 동등성(equality)

 자바에서 동일성은 두 객체가 같다는 뜻이다. 즉 참조하는 주소값이 같다는 뜻이다, 아무리 객체 안 데이터 구조안에 값이 같아도 참조하는 주소값이 다른면 다른것이다.

동등성은 주소값은 달라고 되는데 데이터안의 구조와 값이 같다고 보면된다.

Wrapper class

 자바에서는 자료형은 두 가지로 나누어져 있는데 기본 타입(primitive type)과 참조 타입(reference type)으로 나누어진다.

기본 타입은 int, char, float, double.. 이고 참조 타입은 class, interface 등있다. 기본 타입을 객체로 써야 할 경우가있다. 이 경우를 대비해서 자바에서는 기본 타입을 객체로 만든것이 wrapper class 이다. Wrapper Class에서는 기본 타입 클래스, 박싱/언박싱, AutiBoxing/AutoUnBoxing 있는데 그 부분은 따로 설명하겠다.

 

마무리

 예외처리, 호출 부분은 자바에서 중요한게 아니라 어떤 언어에서도 중요하다 그래서 어떤 언어에서도 예외처리방법이나 함수가 호출될 때 매개변수에 인자를 어떤 방식으로 넣어줄건지에 대한 개념은 필수로 알아야 한다. 과제 코드는 아래 사이트에서 참고 하면된다.

https://github.com/jih3508/Java_Study/tree/main/JSCODE_BACKEND_JAVA/JSCODE_JAVA/src/CH06

 

GitHub - jih3508/Java_Study

Contribute to jih3508/Java_Study development by creating an account on GitHub.

github.com

 

728x90
반응형
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함