자바 문법 (계속 기록)

원서연·2023년 10월 27일
0

Exception 추가 내용 (별도로 포스트 만들기)

우선 자바에서 예외 클래스는 두가지가 있다.
(1) Checked Exception, (2) Unchecked Exception

Checked Exception은 알고 있는대로, 처리를 해주지 않으면 컴파일 타임에서부터
오류가 발생하고, 반드시 try-catch를 하거나 명시적으로 throws로 상위 메서드로 전파시켜서 처리를 해야한다.

Unchecked Exception은 컴파일 타임에서 오류가 발생하지 않으며, 명시적으로 throws 지정을 하지 않더라도 자동으로 상위 메서드로 전파가 된다.(이게 스프링부트 기능인줄 알았다)
다만, 마찬가지로 어디에서도 try-catch로 예외를 처리해주지 않으면 결국엔 프로그램이 종료된다.
대표적인 Unchecked Exception 클래스는 Runtime Exception이 있으며 나머지들은 이 클래스를 상속받는다.

사용자 정의 Exception

  • Exception 클래스를 상속 받아 정의한 checked Exception
    • 반드시 오류를 처리 해야만 하는 Exception
    • 예외 처리하지 않으면 컴파일 오류를 발생 시킨다.
  • RuntimeException 클래스를 상속 받아 정의한 unChecked Exception
    • 예외 처리하지 않아도 컴파일 시에는 오류를 발생시키지 않는다.
      • 그래도 예외 처리를 해주는 것이 안정적인 코드이다.
    • 런타임에는 오류가 발생한다.
  • 사용자 정의 Exception을 사용하는 이유
    • 클래스의 이름만 봐도 어떤 오류가 발생했는지를 사용자에게 직관적으로 알게 하기 위한 목적이다.
    public class BizException extends RuntimeException {
        public BizException(String msg){
            super(msg);
        }       
        public BizException(Exception ex){
            super(ex);
        }
    }

Throw

  • Exception 발생시키기
  • 강제로 오류를 발생시키는 throw
  • throw는 오류를 떠넘기는 throws와 보통 같이 사용됩니다.
    • throws와 같이 사용하지 않았으면, throw 부분을 try~catch 블록 처리를 해야합니다.
    public class ExceptionExam3 {   
        public static void main(String[] args) {
            int i = 10;
            int j = 0;
            try{
                int k = divide(i, j);
                System.out.println(k);
            }catch(IllegalArgumentException e){
                System.out.println("0으로 나누면 안됩니다.");
            }           
        }

        public static int divide(int i, int j) throws IllegalArgumentException{
            if(j == 0){
                throw new IllegalArgumentException("0으로 나눌 수 없어요.");
            }
            int k = i / j;
            return k;
        }   
    }

Throws

  • throws는 예외가 발생했을때 예외를 호출한 쪽에서 처리하도록 던져준다.
  • divide메소드는 ArithmeticException이 발생하니
    divide메소드를 호출하는 쪽에서 오류를 처리하라는 뜻입니다.
  • throws하는 Exception 종류는 여러 가지로 설정할 수 있다.
    • EX)
    public int divide(int i, int j) throws IOException, Exception {...}
    public class ExceptionExam2 {

        public static void main(String[] args) {
            int i = 10;
            int j = 0;
            try{
                int k = divide(i, j);
                System.out.println(k);
            } catch(ArithmeticException e){
                System.out.println("0으로 나눌수 없습니다.");
            }

        }

        public static int divide(int i, int j) throws ArithmeticException{
            int k = i / j;
            return k;
        }

    }

Exception

  • 예외 처리란

    • 프로그램 실행 중 예기치 못한 사건을 예외라고 한다.
    • 예외 상황을 미리 예측하고 처리할 수 있는데, 이렇게 하는 것을 예외 처리라고 한다.
    • 예외가 발생하면 프로그램이 강제 종료된다.
    • 예외 처리를 해주면 프로그램이 강제 종료가 되지 않게 하고, 어떤 예외 상황이 발생했는지 로그를 남기는 등 예외 상황에 대한 처리를 한다.
  • 예외 처리 문법

    • 예외 상황이 예측되는 코드 부분을 try 블록으로 감싸주고 catch 블록으로 Exception을 처리하면 프로그램이 강제종료되지 않는다.
    • try 블록에서 여러 종류의 Exception이 발생한다면 catch 블록을 여러 개 둘 수 있다.
    • 오류가 발생했든 안했든 무조건 실행되는 finally라는 블록을 가질 수 있다.
      • finally 블록은 생략이 가능하다.
  • Exception 클래스

    • ~Exception 클래스들은 모두 Exception 클래스를 상속 받으므로, catch 부분에 Exception을 두게 되면 어떤 오류가 발생하든지 간에 하나의 catch 블록에서 모든 오류를 처리할 수 있다.
    public class ExceptionExam {
        public static void main(String[] args) {
            int i = 10;
            int j = 0;
            try {
                int k = i / j;
                System.out.println(k);
            } catch (ArithmeticException e){
                System.out.println("0으로 나눌 수 없습니다. : " + e.toString());
            } catch (Exception e){
                System.out.println("모든 오류 처리가 가능합니다. : " + e.toString());
            } finally {
                System.out.println("오류가 발생하든 안하든 무조건 실행되는 블록입니다.");
            }
        }
    }

내부 클래스(4가지)

  1. 첫 번째는 필드 위치에 선언되는 경우. 중첩 클래스 또는 인스턴스 클래스라고 한다.
    public class InnerExam1{
        class Cal{
            int value = 0;
            public void plus(){
                value++;
            }
        }
        public static void main(String args[]){
            InnerExam1 t = new InnerExam1();
            InnerExam1.Cal cal = t.new Cal();
            cal.plus();
            System.out.println(cal.value);
        }
    }
  1. 두 번째는 내부 클래스가 static으로 정의된 경우. 정적 중첩 클래스 또는 static 클래스라고 한다.
    public class InnerExam2{
        static class Cal{
            int value = 0;
            public void plus(){
                value++;
            }
        }
        public static void main(String args[]){
            InnerExam2.Cal cal = new InnerExam2.Cal();
            cal.plus();
            System.out.println(cal.value);
        }
    }
  1. 세 번째는 메서드 안에 클래스를 선언한 경우. 지역 중첩 클래스 또는 지역 클래스라고 한다.
    public class InnerExam3{
        public void exec(){
            class Cal{
                int value = 0;
                public void plus(){
                    value++;
                }
            }
            Cal cal = new Cal();
            cal.plus();
            System.out.println(cal.value);
        }
        public static void main(String args[]){
            InnerExam3 t = new InnerExam3();
            t.exec();
        }
    }
  1. 네 번째는 익명 중첩 클래스 또는 익명 클래스라고 한다.(보통 익명 클래스라고 한다.)
    //추상클래스 Action 
    public abstract class Action{
        public abstract void exec();
    }

    //추상클래스 Action을 상속받은 클래스 MyAction

    public class MyAction extends Action{
        public void exec(){
            System.out.println("exec");
        }
    }

    //MyAction을 사용하는 클래스 ActionExam 
    public class ActionExam{
        public static void main(String args[]){
            Action action = new MyAction();
            action.exec();
        }
    }

    //MyAction을 사용하지 않고 Action을 상속받는 익명 클래스를 만들어서 사용하도록 수정해 보도록 하겠습니다.
    public class ActionExam{
        public static void main(String args[]){
            Action action = new Action(){
                public void exec(){
                    System.out.println("exec");
                }
            };
            action.exec();
        }
    }
  • 생성자 다음에 중괄호 열고 닫고가 나오면, 해당 생성자 이름에 해당하는 클래스를 상속받는 이름없는 객체를 만든다는 것을 뜻한다.
  • 괄호 안에는 메소드를 구현하거나 메소드를 추가할 수 있다. 이렇게 생성된 이름 없는 객체를 action이라는 참조변수가 참조하도록 하고, exec()메소드를 호출.
  • 익명클래스를 만드는 이유는 Action을 상속받는 클래스를 만들 필요가 없을 경우이다.
  • Action을 상속받는 클래스가 해당 클래스에서만 사용되고 다른 클래스에서는 사용되지 않는 경우이다.

static 메서드 (in 클래스)

  • static 키워드를 붙이면 클래스 레벨에 속하는 메서드가 된다.

  • '클래스명.메서드명'과 같이 호출이 가능하다.

    인스턴스로부터 호출도 할 수 있다.

    • 그러나 static 메서드를 인스턴스로부터 호출하는 것은 권장되지 않는 방법이다.
    • static 메서드는 클래스 레벨에서 직접 호출하는 것이 더 자연스럽고 명확하다.

static 메서드 (in 인터페이스)

  • static 키워드를 붙이면 클래스 레벨에 속하는 메서드가 된다.

  • '클래스명.메서드명'과 같이 호출이 가능하다.

    인스턴스로부터 호출은 불가능하다.

    • 해당 인터페이스를 구현한 클래스를 인스턴스화 하고서
      해당 인스턴스로부터 static 메서드를 호출하려고 하면 되지 않는다.
profile
웹 백엔드 프로그래밍 Today I Learned

0개의 댓글