Java/문법

[Java] 핵심 기본편 - 익명 클래스, 람다와 스트림, 예외 처리(Try Catch, Throw, Finally, Try With Resource, 사용자 정의 예외, Throws)

Se On 2024. 7. 4. 16:08

1. 익명클래스, 람다와 스트림

익명클래스

  • 익명클래스: 한 번만 사용되는 이름 없는 클래스
  • main 메소드에서 클래스를 호출한 뒤 {@Override}
// Person 클래스
class Person {
    public void introduce() {
        System.out.println("사람입니다");
    }
}

// main 메소드
public static void main(String[] args) {
    Person person = new Person();
    person.introduce(); // 사람입니다
}

// 익명 클래스 - Person 클래스의 introduce라는 동작을 변경할 수 있음
public static void main(String[] args) {
    Person person = new Person();
        // 익명클래스
        @Override
        public void introduce() {
            System.out.println("익명입니다");
        }
    };
    person.introduce(); // 익명입니다
}

 

람다식

  1. 람다식: 간결한 형태의 코드 묶음, 메소드의 동작을 간단히 표현하기 위해 사용함
  2. (전달값1, 전달값2, ...) -> {코드}
  3. 순서
    1. 접근제어자, 반환형, 이름 제거
    2. 기호 삽입
    3. 각 전달값의 자료형 제거
    4. 중괄호, return 키워드 제거
    1. add 메소드
      public int add(int x, int y) {
          return x + y;
      }
    2. 람다식으로 변경
      (x, y) -> x + y
// add 메소드 - 두 수의 합을 return
public int add(int x, int y) {
	return x + y;
}

/* 위 메소드를 람다식으로 바꾸려면
1. 접근제어자, 반환형, 이름 제거
(int x, int y) {
	return x + y;
}

2. 기호 삽입
(int x, int y) -> {
	return x + y;
}

3. 각 전달값의 자료형 제거
(x, y) -> {
    return x + y;
}

4. 중괄호, return 제거(중괄호 제거는 메소드의 동작이 하나의 문장으로 이루어진 경우에만 가능)
(x, y) ->  + y */

 

함수형 인터페이스

  1. 함수형 인터페이스: 람다식을 위한 인터페이스
  2. 제약사항: 딱 하나의 추상 메소드를 가져야 함
  3. @FunctionalInterface
    interface 인터페이스명 {
        // 하나의 추상 메소드
    }
// 함수형 인터페이스
@FuntionalInterface
interface Calculator {
	int calculate(int x, int y); // calculate 추상 메소드
}

// 메인 메소드
public static void main(String[] args) {
    Calculator add = (x, y) -> x + y; // 람다식
    int result = add.calculate(2, 3); // calculate 메소드 매핑
    System.out.println("2 + 3 = " + result); // 2 + 3 = 5
}

 

스트림

  1. 스트림: 배열, 컬렉션 데이터를 효과적으로 처리
// 정수형 데이터를 저장한 리스트
public static void main(String[] args) {
    List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
    // 스트림
    numbers.stream()
        .filter(n -> n % 2 == 0) // 짝수만 필터링
        .map(n -> n * 2) // 각 요소 값을 2배로 변환
        .forEach(System.out.println); // 결과 출력: 4, 8
}

 

 

2. 예외처리

예외 처리(Try Catch)

  • 예외 처리: 프로그램 내에서 발생 가능한 문제 상황을 처리하는 것
  • try {
        명령문 // 명령문을 수행하다가 문제가 발생하면
    } catch (변수) {
        예외 처리 // catch문을 통해서 예외 처리 수행하는 것
    }
public static void main(String[] args) {
    int[] numbers = {1, 2, 3};
    int index = 5; // 존재하지 않는 인덱스
    // 예외처리
    try {
        int result = numbers[index]; // numbers[5]는 존재하지 않기에 catch문으로
        System.out.println("결과: " + result);
    } catch (Exception e) {
        System.out.println("문제 발생"); // 문제 발생
    }
}

 

Catch

  • Catch: 예외의 종류에 따른 처리를 위해 사용함
  • try {
        명령문
    } catch (변수1) {
        예외 처리 1
    } catch (변수2) {
        예외 처리 2
    }
public static void main(String[] args) {
    int[] numbers = {1, 2, 3};
    int index = 5; // 존재하지 않는 인덱스
    // 예외처리
    try {
        int result = numbers[index];
        System.out.println("결과: " + result);
    } catch (ArrayIndexOutOfBoundsException e) { // 잘못된 인덱스에 접근하려고 할 때에만 실행
        System.out.println("문제 발생"); // 문제 발생
    }
}

 

예외 발생 시키기(Throw)

  • 예외 발생 시키기: 의도적으로 예외 상황 만들기
  • throw new 예외();
public static void main(String[] args) {
    try {
        int age = -5;
        if (age < 0) {
            throw new Exception("나이는 음수일 수 없습니다");
        }
    } catch (Exception e) {
        System.out.println(e.getMessage()); // 나이는 음수일 수 없습니다 메세지 출력
    }
}

 

Finally

  • Finally: (예외가 발생하든말든) 항상 실행되는 코드
  • try {
        명령문
    } catch (변수) {
        예외 처리
    } finally {
        명령문
    }
// 실패 시에도 실행되고
public static void main(String[] args) {
    try {
        int result = 3 / 0; // 0으로 나누기 실패하면
    } catch (Exception e) {
        System.out.println("문제 발생"); // 문제 발생
    } finally {
        System.out.println("실행 종료"); // 실행 종료(언제나 실행됨)
    }
}

// 성공 시에도 실행됨
public static void main(String[] args) {
    try {
        int result = 4 / 2; // 2로 나누기 성공하면
    } catch (Exception e) {
        System.out.println("문제 발생");
    } finally {
        System.out.println("실행 종료"); // 실행 종료(언제나 실행됨)
    }
}

 

Try With Resource

  • Try With Resource: 리소스 관리를 편하게 할 수 있는 방법
    • Try문에서 자원할당
    • 빠져나올 때 자동으로 자원 해제
  • try (자원할당) {
        명령문
    } catch (변수) {
        예외 처리
    }
public static void main(String[] args) {
    try(FileWriter writer = new FileWriter("file.txt")) { // file.txt 파일을 열어서 writer에 쓰도록 자원 할당
        writer.write("안녕?"); // try문을 빠져나올 때 finally문에서 자원 해제하지 않아도, 자동으로 자원 해제를 수행함
    } catch (Exception e) {
        System.out.println("문제 발생");
    }
}

 

사용자 정의 예외

  • 사용자 정의 예외: 개발자가 직접 정의한 예외 클래스 (특정 상황에서 발생 시키고자 할 때 사용될 수 있는 예외)
  • class 클래스명 extends Exception {

    }
    • Exception 클래스를 상속하여 만들 수 있음
// MyException: 사용자 정의 예외
class MyException extends Exception { // Exception 클래스를 상속하여 코드 작성
    public MyException(String message) { 
        super(message);
    }
}

// 메인 메소드 try & catch 구문
public static void main(String[] args) {
    try {
        int age = 15;
        if (age < 0) {
            throw new MyException("나이는 음수일 수 없습니다"); // 예외 발생
        }
    } catch (MyException e) { // 사용자 정의 예외 처리
        System.out.println("문제 발생: " + e.getMessage());
    }
}

 

예외 처리 미루기(Throws)

  • 예외 처리 미루기: 메소드를 수행하다가 문제가 발생했을 때 메소드를 호출한 곳에서 처리하는 것
  • 반환형 메소드명() throws 예외 {
        명령문
    }
    • 메소드를 수행하다가 문제 발생 시, 그 예외를 메소드를 호출한 쪽으로 throws 던지는 것!
// divide 메소드 (문제 발생 시, 메소드를 호출한 쪽에서 예외처리 하도록)
public static int divide(int a, int b) thorw Exception {
	return a / b; // 3 / 0: 문제 발생
}

// 메인 메소드
public static void main(String[] args) {
    try {
        divide(3, 0); // divide 메소드를 호출한 것은 메인 메소드이기 때문에
    } catch (Exception e) { // 메인 메소드에서 예외 처리
        System.out.println("0으로 나눌 수 없어요");
    }
}

 

 


참고 영상: 나도코딩 - 자바 무료 강의 2시간 완성(1분 자바)

https://youtu.be/DNCBaeCoMug?si=VM02QD9igeT561pp

 

반응형