본문 바로가기

WINK-(Web & App)/JAVA 스터디

[2024-2 Java 스터디] 김지나 #7주차

반응형

07-04. 예외 처리

 

✅ 예외는 언제 발생하는가?

- FileNotFoundException: 존재하지 않는 파일을 열려고 시도했을 때

- ArithmeticException: 산술에 문제가 생겼을 때

- ArrayIndexOutOfBoundsException: 정해진 배열의 크기보다 크거나 음수 인덱스를 요청했을 때 

 

 

✅ 예외 처리하기

① try ~ catch문

// 기본 구조
try {
    <수행할 문장 1>;
    <수행할 문장 2>;
    ...
} catch(예외1) {
    <수행할 문장 A>;
    ...
} catch(예외2) {
    <수행할 문장 a>;
    ...
}

- try 문 안에서 예외가 발생하지 않으면 catch 수행 x

 

② finally

-예외가 발생하더라도 실행됨

public class Sample {
    public void shouldBeRun() {
        System.out.println("ok thanks");
    }

    public static void main(String[] args) {
        Sample sample = new Sample();
        int c;
        try {
            c = 4 / 0;
            // sample.shouldBeRun();
            // 여기 코드가 있으면 오류 발생 -> catch문으로 가기 때문에 실행 x
        } catch (ArithmeticException e) { 
            c = -1;
        } finally {
            sample.shouldBeRun(); // 무조건 실행됨
        }
    }
}

 

 

✅ RuntimeException과 Exception

- RuntimeException: 실행 시 발생하는 예외, 예측이 불가능한 경우 ( = Unchekced Exception )

- Exception: 컴파일 시 발생하는 예외, 예측 가능한 경우 ( = Checked Exception )

// RuntimeException
class FoolException extends RuntimeException {
}

public class Sample {
    public void sayNick(String nick) {
        if("바보".equals(nick)) {
            throw new FoolException(); // Exception 발생
        }
        System.out.println("당신의 별명은 "+nick+" 입니다.");
    }

    public static void main(String[] args) {
        Sample sample = new Sample();
        sample.sayNick("바보");
        sample.sayNick("야호");
    }
}
// Exception
class FoolException extends Exception {
}

public class Sample {
    public void sayNick(String nick) {
        try {
            if("바보".equals(nick)) {
                throw new FoolException();
            }
            System.out.println("당신의 별명은 "+nick+" 입니다.");
        }catch(FoolException e) { // try ~ catch 문으로 처리
            System.err.println("FoolException이 발생했습니다.");
        }
    }

    public static void main(String[] args) {
        Sample sample = new Sample();
        sample.sayNick("바보");
        sample.sayNick("야호");
    }
}

 

 

✅ 예외 던지기

- throws 구문을 이용해 예외를 위로 던짐

class FoolException extends Exception {
}

public class Sample {
    public void sayNick(String nick) throws FoolException { // throws 사용
        if("바보".equals(nick)) {
            throw new FoolException();
        }
        System.out.println("당신의 별명은 "+nick+" 입니다.");
    }

    public static void main(String[] args) {
        Sample sample = new Sample();
        try {
            sample.sayNick("바보");
            sample.sayNick("야호");
        } catch (FoolException e) {
            System.err.println("FoolException이 발생했습니다.");
        }
    }
}

- throw: 메서드 내에서 예외를 발생시킬 때

- throws: 메서드 선언부에서 사용, 해당 메서드가 처리하지 않은 예외를 호출자에게 전달

 

 

✅ 트랜잭션

- 예외가 하나라도 발생하면 모두 취소

상품발송() {
    try {
        포장();
        영수증발행();
        발송();
    }catch(예외) {
        모두취소();  
    }
}

포장() throws 예외 {
   ...
}

영수증발행() throws 예외 {
   ...
}

발송() throws 예외 {
   ...
}

 

 

 

07-05. 스레드

 

✅ Thread

- 스레드는 순서에 상관없이 동시에 실행됨

- 스레드가 종료되기 전에 main 메서드가 종료됨

public class Sample extends Thread { // 스레드 상속
    int seq;

    public Sample(int seq) {
        this.seq = seq;
    }

    public void run() { // run 메서드 구현
        System.out.println(this.seq + " thread start.");  // 스레드 시작
        try {
            Thread.sleep(1000);  // 1초 대기
        } catch (Exception e) {
        }
        System.out.println(this.seq + " thread end.");  // 스레드 종료 
    }

    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {  
            Thread t = new Sample(i);
            t.start(); // start 메서드 실행 -> run 메서드 수행
        }
        System.out.println("main end.");  // main 메서드 종료
    }
}

/* 출력:
0 thread start.
4 thread start.
6 thread start.
2 thread start.
main end.
3 thread start.
7 thread start.
8 thread start.
... */

 

 

✅ Join

- 스레드가 종료될 때까지 기다리게 하는 메서드

import java.util.ArrayList;

public class Sample extends Thread {
    int seq;
    public Sample(int seq) {
        this.seq = seq;
    }

    public void run() {
        System.out.println(this.seq+" thread start.");
        try {
            Thread.sleep(1000);
        }catch(Exception e) {
        }
        System.out.println(this.seq+" thread end.");
    }

    public static void main(String[] args) {
        ArrayList<Thread> threads = new ArrayList<>();
        for(int i=0; i<10; i++) {
            Thread t = new Sample(i);
            t.start();
            threads.add(t);
        }

        for(int i=0; i<threads.size(); i++) {
            Thread t = threads.get(i);
            try {
                t.join(); // 스레드가 종료될 때까지 기다림
            }catch(Exception e) {
            }
        }
        System.out.println("main end."); // 스레드가 종료되고 main 종료
    }
}

 

 

✅ Runnable

- 스레드 클래스를 상속하면 상속한 클래스가 다른 클래스를 상속할 수 없는 문제로 인해 Runnable 인터페이스 사용, 유연성 ⬆️

import java.util.ArrayList;

public class Sample implements Runnable { // Runnable 인터페이스는 run 메서드를 구현하도록 강제
    int seq;
    public Sample(int seq) {
        this.seq = seq;
    }

    public void run() {
        System.out.println(this.seq+" thread start.");
        try {
            Thread.sleep(1000);
        }catch(Exception e) {
        }
        System.out.println(this.seq+" thread end.");
    }

    public static void main(String[] args) {
        ArrayList<Thread> threads = new ArrayList<>();
        for(int i=0; i<10; i++) {
            Thread t = new Thread(new Sample(i));
            t.start();
            threads.add(t);
        }

        for(int i=0; i<threads.size(); i++) {
            Thread t = threads.get(i);
            try {
                t.join();
            }catch(Exception e) {
            }
        }
        System.out.println("main end.");
    }
}

 

 

07-06. 함수형 프로그래밍

 

✅ 람다 

- 익명 함수를 의미함

// 일반적인 코드
interface Calculator { 
    int sum(int a, int b);
}

class MyCalculator implements Calculator { Calculator 인터페이스를 구현한 클래스 생성
    public int sum(int a, int b) {
        return a+b;
    }
}

public class Sample {
    public static void main(String[] args) {
        MyCalculator mc = new MyCalculator();
        int result = mc.sum(3, 4);
        System.out.println(result);  // 7 출력
    }
}
// 람다를 사용한 코드
interface Calculator {
    int sum(int a, int b);
}

public class Sample {
    public static void main(String[] args) {
        Calculator mc = (int a, int b) -> a +b;  // 람다를 적용한 코드
        int result = mc.sum(3, 4);
        System.out.println(result); // 7 출력
    }
}

// 축약한 코드
interface Calculator {
    int sum(int a, int b);
}

public class Sample {
    public static void main(String[] args) {
        Calculator mc = (a, b) -> a +b; // 입출력 타입 정의 O -> 자료형 생략 가능
        int result = mc.sum(3, 4);
        System.out.println(result);
    }
}

- Calculator 인터페이스의 메서드가 1개 이상이면 람다 함수를 사용할 수 없음

=> 람다 함수를 사용할 인터페이스는 @FuntionalInterface 어노테이션을 사용하는 것이 좋음 (인터페이스가 단 하나의 메서드만 가지도록 함) 

 

 

✅ 스트림

- 데이터가 필터링 과정을 통해 여러 번 변경되어 반환됨

int[] data = {5, 6, 4, 2, 3, 1, 1, 2, 2, 4, 8}; 
// 이 배열에서 짝수만 뽑아 중복 제거 후 역순으로 정렬하는 프로그램을 만들어보자
int[] result = {8, 6, 4, 2}; // 수행 결과

// 일반적인 코드
import java.util.*;

public class Sample {
    public static void main(String[] args) {
        int[] data = {5, 6, 4, 2, 3, 1, 1, 2, 2, 4, 8};

        ArrayList<Integer> dataList = new ArrayList<>(); // 짝수만 포함하는 ArrayList 생성
        for(int i=0; i<data.length; i++) {
            if(data[i] % 2 == 0) {
                dataList.add(data[i]);
            }
        }

        HashSet<Integer> dataSet = new HashSet<>(dataList); // 중복 제거

        ArrayList<Integer> distinctList = new ArrayList<>(dataSet); // Set -> List

        distinctList.sort(Comparator.reverseOrder()); // 역순 정렬

        int[] result = new int[distinctList.size()];
        for(int i=0; i< distinctList.size(); i++) {
            result[i] = distinctList.get(i); // 정수 배열로 반환
        }
    }
}

// 스트림을 적용한 코드
import java.util.Arrays;
import java.util.Comparator;

public class Sample {
    public static void main(String[] args) {
        int[] data = {5, 6, 4, 2, 3, 1, 1, 2, 2, 4, 8};
        int[] result = Arrays.stream(data)  // IntStream 생성
                .boxed()  // Stream<Integer>로 변경
                .filter((a) -> a % 2 == 0)  //  짝수만 뽑아냄
                .distinct()  // 중복 제거 
                .sorted(Comparator.reverseOrder())  // 역순 정렬
                .mapToInt(Integer::intValue)  // IntStream으로 변경
                .toArray()  // int[] 배열로 반환
                ;
    }
}

 


객관식

Q1. Java에서 try 블록에 포함할 수 없는 것은 무엇인가요?

A1. B) catch 블록

 

Q2. finally 블록의 실행 시점은 언제인가요?

A2. C) try 블록 이후 항상 실행된다

 

Q3. 다음 코드에서 출력 결과는?

public class Test {
    public static void main(String[] args) {
        try {
            int result = 10 / 0;
        } catch (ArithmeticException e) {
            System.out.println("Arithmetic Exception");
        } finally {
            System.out.println("Finally Block");
        }
    }
}

A3. C) Arithmetic ExceptionFinally Block 

 

Q4. 다음 코드에서 catch 블록이 처리할 수 있는 예외는?

public class Test {
    public static void main(String[] args) {
        try {
            String s = null;
            System.out.println(s.length());
        } catch (ArithmeticException e) {
            System.out.println("Arithmetic Exception");
        }
    }
}

A4. C) 아무 것도 처리하지 않음

 

Q5. throw와 throws의 차이는 무엇인가요?

A5. B) throw는 예외 발생, throws는 선언

 

Q6. catch 블록에서 예외 처리 후 프로그램이 실행을 계속하기 위해 필요한 것은?

A6. C) 올바른 예외 처리가 이루어짐

 

Q7. finally 블록이 실행되지 않을 경우는 언제인가요?

A7. C) JVM이 강제 종료될 때

 

Q8.

public class Test {
    public static void main(String[] args) {
        try {
            System.out.println("Try Block");
            return;
        } finally {
            System.out.println("Finally Block");
        }
    }
}

A8. C) Try BlockFinally Block

 

Q9.

public class Test {
    public static void main(String[] args) {
        try {
            throw new Exception();
        } finally {
            System.out.println("Finally Block");
        }
    }
}

A9. A) Finally BlockException 발생

 

Q10. 

public class Test {
    public static void main(String[] args) {
        try {
            throw new RuntimeException();
        } catch (Exception e) {
            System.out.println("Catch Block");
        } finally {
            System.out.println("Finally Block");
        }
    }
}

A10. C) Catch BlockFinally Block

 

Q11. Java 8에서 스트림(Stream)의 주요 특징이 아닌 것은?

A11. B) 데이터 변경 가능

 

Q12. 람다 표현식의 문법 중 올바르지 않은 것은?

A12. D) (x, y) -> { return; x + y; }

 

Q13.

import java.util.stream.Stream;

public class Main {
    public static void main(String[] args) {
        Stream.of(1, 2, 3, 4)
              .filter(x -> x % 2 == 0)
              .forEach(System.out::print);
    }
}

A13. B) 24

 

Q14. 람다 표현식과 메서드 참조의 차이는?

A14. C) 람다는 메서드 참조보다 유연성이 높다

 

Q15. 다음 스트림 코드의 출력 결과는?

import java.util.stream.IntStream;

public class Main {
    public static void main(String[] args) {
        int sum = IntStream.range(1, 5).reduce(0, Integer::sum);
        System.out.println(sum);
    }
}

A15. A) 10 

 

Q16. Java의 함수형 프로그래밍에서 "고차 함수"란 무엇인가요?

A16. B) 다른 함수를 매개변수로 받거나 반환하는 함수

 

Q17. 다음 코드는 어떤 스트림 연산을 사용하고 있나요?

Stream.of("a", "b", "c")
      .map(String::toUpperCase)
      .forEach(System.out::println);

A17. B) 매핑

 

코드 실행 결과 예측 문제

Q1.

import java.util.function.Function;

public class Main {
    public static void main(String[] args) {
        Function<String, Integer> length = String::length;
        System.out.println(length.apply("Lambda"));
    }
}

A1. B) 6

 

Q2.

import java.util.Arrays;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<String> list = Arrays.asList("a", "b", "c");
        list.stream()
            .filter(x -> x.equals("b"))
            .forEach(System.out::print);
    }
}

A2. B) b

 

Q3.

import java.util.stream.IntStream;

public class Main {
    public static void main(String[] args) {
        IntStream.range(1, 5)
                 .map(x -> x * x)
                 .forEach(System.out::print);
    }
}

A3. A) 14916

 

Q4.

import java.util.Optional;

public class Main {
    public static void main(String[] args) {
        Optional<String> optional = Optional.of("Lambda");
        System.out.println(optional.orElse("Default"));
    }
}

A4. A) Lambda

 

Q5.

import java.util.stream.Stream;

public class Main {
    public static void main(String[] args) {
        Stream.of("A", "B", "C")
              .filter(s -> s.startsWith("B"))
              .forEach(System.out::println);
    }
}

A5. B) B

 

코테 

Q1. 백준 #2920

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int[] notes = new int[8];
        for (int i = 0; i < 8; i++) {
            notes[i] = sc.nextInt();
        }
        sc.close();

        boolean ascending = true;
        boolean descending = true;

        for (int i = 0; i < 7; i++) {
            if (notes[i] < notes[i + 1]) {
                descending = false;
            } else if (notes[i] > notes[i + 1]) {
                ascending = false;
            }
        }

        if (ascending) {
            System.out.println("ascending");
        } else if (descending) {
            System.out.println("descending");
        } else {
            System.out.println("mixed");
        }
    }
}

 

 

Q2. 백준 #1259

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        
        while (true) {
            String num = sc.next(); 
            
            if (num.equals("0")) {
                break;
            }
            
            String reversed = new StringBuilder(num).reverse().toString();
            
            if (num.equals(reversed)) {
                System.out.println("yes"); 
            } else {
                System.out.println("no"); 
            }
        }
        
        sc.close();
    }
}

 


 

반응형