목차
- 예외처리
- 스레드
- 함수형 프로그래밍
자바에서 예외처리와 스레드, 함수형 프로그래밍에 대해 알아보자
1. 자바에서 예외 처리
자바에서 예외는 프로그램 실행 중 발생할 수 있는 오류를 말한다.
예외 처리는 프로그램이 예기치 않게 종료되지 않도록 하기 위해 중요하며 예외처리 시 ry-catch 문을 사용한다.
예외 처리 기본 구조
try {
// 예외가 발생할 수 있는 코드
int result = 10 / 0; // 예외 발생
} catch (ArithmeticException e) {
// 예외가 발생했을 때 처리할 코드
System.out.println("0으로 나눌 수 없습니다.");
} finally {
// 예외 여부와 상관없이 실행되는 코드
System.out.println("이 코드는 항상 실행됩니다.");
}
예외 던지기
메서드에서 예외를 처리하지 않고 호출자에게 예외를 전달할 수 있다. 이를 위해 throws 키워드를 사용한다.
public void someMethod() throws IOException {
// 예외가 발생할 수 있는 코드
}
2. 자바에서 스레드
스레드는 프로그램 내에서 독립적으로 실행되는 작업 단위로 자바에서 스레드를 구현하는 방법에는 두 가지가 있다. Thread 클래스를 상속하거나 Runnable 인터페이스를 구현하는 방법이다!
스레드 생성 방법 1: Thread 클래스 상속
class MyThread extends Thread {
public void run() {
System.out.println("스레드가 실행 중입니다.");
}
}
public class ThreadExample {
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start(); // 스레드 시작
}
}
스레드 생성 방법 2: Runnable 인터페이스 구현
class MyRunnable implements Runnable {
public void run() {
System.out.println("스레드가 실행 중입니다.");
}
}
public class ThreadExample {
public static void main(String[] args) {
MyRunnable myRunnable = new MyRunnable();
Thread thread = new Thread(myRunnable);
thread.start(); // 스레드 시작
}
}
3. 자바에서 함수형 프로그래밍
자바 8부터 함수형 프로그래밍을 지원하는 람다 표현식과 스트림 API가 도입되었다.
이를 통해 코드가 더 간결해지고 함수형 스타일로 작성할 수 있게 됐다.
람다 표현식
람다는 익명 함수로, 메서드를 간결하게 표현할 수 있는 방법이다.
interface Greeting {
void greet(String name);
}
public class LambdaExample {
public static void main(String[] args) {
Greeting greeting = (name) -> System.out.println("Hello, " + name);
greeting.greet("Alice"); // 출력: Hello, Alice
}
}
스트림 API
스트림은 컬렉션을 처리하는 데 유용한 도구로,
데이터를 처리하는 과정에서 반복문을 사용하는 대신 함수형 스타일의 연산을 사용할 수 있다.
import java.util.Arrays;
import java.util.List;
public class StreamExample {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
// 짝수만 필터링하여 출력
numbers.stream()
.filter(n -> n % 2 == 0)
.forEach(System.out::println); // 출력: 2, 4
}
}
스트림의 주요 연산
스트림의 주요 연산은 다음과 같다.
- filter(): 조건에 맞는 요소만 필터링
- map(): 각 요소에 대해 변환 작업 수행
- reduce(): 모든 요소를 하나로 결합
import java.util.Arrays;
import java.util.List;
public class StreamExample {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
// 모든 숫자의 합 구하기
int sum = numbers.stream()
.reduce(0, (a, b) -> a + b);
System.out.println("합: " + sum); // 출력: 15
}
}
객관식 문제
1. Java에서 try 블록에 포함할 수 없는 것은 무엇인가요?
- A) 예외를 발생시킬 가능성이 있는 코드
- B) catch 블록
- C) 일반 코드
- D) throw 키워드
정답: B) catch 블록
해설: catch 블록은 try 블록 밖에 위치해야 한다. throw는 예외를 던질 때 사용되므로 try 블록 안에서 사용할 수 있다.
2. finally 블록의 실행 시점은 언제인가요?
- A) 예외가 발생하지 않을 때만 실행된다
- B) 예외가 발생할 때만 실행된다
- C) try 블록 이후 항상 실행된다
- D) catch 블록 이후 선택적으로 실행된다
정답: C) try 블록 이후 항상 실행된다
해설: finally 블록은 예외 발생 여부와 관계없이 항상 실행된다. 예외가 발생하지 않아도 실행되고, 예외가 발생하면 catch 블록 실행 후에 실행된다.
3. 다음 코드에서 출력 결과는?
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");
}
}
}
- A) Arithmetic Exception
- B) Finally Block
- C) Arithmetic ExceptionFinally Block
- D) 컴파일 오류 발생
정답: C) Arithmetic ExceptionFinally Block
해설: try 블록에서 예외가 발생하면 catch 블록에서 처리하고, finally 블록은 항상 실행된다. 그래서 "Arithmetic Exception"과 "Finally Block"이 차례대로 출력된다.
4. 다음 코드에서 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");
}
}
}
- A) ArithmeticException
- B) NullPointerException
- C) 아무 것도 처리하지 않음
- D) IOException
정답: C) 아무 것도 처리하지 않음
해설: catch 블록은 ArithmeticException만 처리할 수 있는데, 이 코드에서 발생한 예외는 NullPointerException이다. 따라서 catch 블록은 예외를 처리하지 않으며, 예외는 프로그램 밖으로 던져진다.
5. throw와 throws의 차이는 무엇인가요?
- A) 동일한 기능을 수행한다
- B) throw는 예외 발생, throws는 선언
- C) throw는 Checked Exception, throws는 Unchecked Exception
- D) 둘 다 예외를 발생시킨다
정답: B) throw는 예외 발생, throws는 선언
해설: throw는 예외를 발생시키는 데 사용되며, throws는 메서드에서 발생할 수 있는 예외를 호출자에게 전달할 때 사용된다.
6. catch 블록에서 예외 처리 후 프로그램이 실행을 계속하기 위해 필요한 것은?
- A) finally 블록
- B) 예외가 다시 발생하지 않음
- C) 올바른 예외 처리가 이루어짐
- D) 위 모든 것
정답: D) 위 모든 것
해설: 예외 처리가 끝난 후 프로그램이 정상적으로 실행되려면 catch 블록에서 예외가 다시 발생하지 않도록 처리가 되어야 한다. finally 블록도 필요하고, 예외 처리가 올바르게 되어야 한다.
7. finally 블록이 실행되지 않을 경우는 언제인가요?
- A) 예외가 발생하지 않을 때
- B) 예외가 발생할 때
- C) JVM이 강제 종료될 때
- D) 프로그램이 정상적으로 실행될 때
정답: C) JVM이 강제 종료될 때
해설: finally 블록은 예외 발생 여부와 관계없이 항상 실행된다. 단, System.exit() 같은 명령어로 JVM이 강제 종료되면 finally 블록은 실행되지 않는다.
8. 문제 3:
public class Test {
public static void main(String[] args) {
try {
System.out.println("Try Block");
return;
} finally {
System.out.println("Finally Block");
}
}
}
- A) Try Block
- B) Finally Block
- C) Try BlockFinally Block
- D) 아무 것도 출력되지 않음
정답: C) Try BlockFinally Block
해설: return 문은 메서드를 종료시키지만, finally 블록은 항상 실행된다. 그래서 "Try Block"과 "Finally Block"이 차례대로 출력된다.
9. 문제 4:
public class Test {
public static void main(String[] args) {
try {
throw new Exception();
} finally {
System.out.println("Finally Block");
}
}
}
- A) Finally Block
- B) Exception 발생
- C) Finally BlockException 발생
- D) 아무 것도 출력되지 않음
정답: C) Finally BlockException 발생
해설: throw로 예외를 던지면 finally 블록이 실행된 후 예외가 발생한다. 예외는 finally 블록 이후에 던져지기 때문에 예외 메시지는 출력되지 않는다.
10. 문제 5:
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");
}
}
}
- A) Catch Block
- B) Finally Block
- C) Catch BlockFinally Block
- D) 아무 것도 출력되지 않음
정답: C) Catch BlockFinally Block
해설: RuntimeException은 Exception의 자식 클래스이므로 catch 블록에서 처리된다. 이후 finally 블록이 항상 실행된다.
11. Java 8에서 스트림(Stream)의 주요 특징이 아닌 것은?
- A) 지연 연산(Lazy Evaluation)을 지원
- B) 데이터 변경 가능
- C) 병렬 처리 가능
- D) 선언형 스타일
정답: B) 데이터 변경 가능
해설: 스트림은 불변 객체로 데이터를 변경할 수 없다. 스트림 연산은 원본 데이터를 변경하지 않고 새 데이터를 생성한다.
12. 람다 표현식의 문법 중 올바르지 않은 것은?
- A) (x, y) -> x + y
- B) x -> { return x * x; }
- C) (int x) -> { return x * x; }
- D) (x, y) -> { return; x + y; }
정답: D) (x, y) -> { return; x + y; }
해설: return; 구문은 void 메서드에서만 사용된다. x + y를 반환하려면 return x + y;로 작성해야 한다.
13. 다음 스트림 코드에서 출력 결과는?
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);
}
}
- A) 1234
- B) 24
- C) 13
- D) 2
정답: B) 24
해설: filter 연산으로 짝수만 선택하여 출력한다. 그래서 2와 4가 출력된다.
14. 람다 표현식과 메서드 참조의 차이는?
- A) 람다는 매개변수를 지원하지 않는다
- B) 메서드 참조는 명시적으로 새 메서드를 작성해야 한다
- C) 람다는 메서드 참조보다 유연성이 더 크다
- D) 람다 표현식은 메서드 참조를 포함한다
정답: C) 람다는 메서드 참조보다 유연성이 더 크다
해설: 람다는 코드 블록을 유연하게 작성할 수 있기 때문에 더 다양한 방식으로 사용할 수 있다. 반면, 메서드 참조는 기존 메서드를 참조하는 방식으로 제한된다.
15. 다음 스트림 코드의 출력 결과는?
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);
}
}
- A) 10
- B) 15
- C) 6
- D) 컴파일 에러
정답: A) 10
해설: IntStream.range(1, 5)는 1부터 4까지의 값을 포함하는 스트림을 생성한다. reduce(0, Integer::sum)는 스트림의 모든 값을 합산하는 연산이다. 1 + 2 + 3 + 4 = 10이 출력된다.
16. Java의 함수형 프로그래밍에서 "고차 함수"란 무엇인가요?
- A) 한 번만 호출되는 함수
- B) 다른 함수를 매개변수로 받거나 반환하는 함수
- C) 정적 메서드를 호출하는 함수
- D) 데이터를 수정하는 함수
정답: B) 다른 함수를 매개변수로 받거나 반환하는 함수
해설: 고차 함수는 다른 함수를 인자로 받거나 다른 함수를 반환하는 함수이다. 함수형 프로그래밍에서 중요한 개념으로, 예를 들어 map, filter 같은 함수들이 고차 함수이다.
17. 다음 코드는 어떤 스트림 연산을 사용하고 있나요?
Stream.of("a", "b", "c")
.map(String::toUpperCase)
.forEach(System.out::println);
- A) 필터링
- B) 매핑
- C) 합산
- D) 병렬 처리
정답: B) 매핑
해설: map 연산은 각 요소를 변환하는 데 사용된다. 이 코드에서는 각 문자열을 대문자로 변환하는 매핑 연산을 사용하고 있다.
코드 실행 결과 예측 문제 (5개)
문제 1:
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"));
}
}
- A) 5
- B) 6
- C) 7
- D) 컴파일 에러
정답: B) 6
해설: String::length는 문자열의 길이를 반환하는 메서드를 참조한다. "Lambda"라는 문자열의 길이는 6이므로 출력은 6이다.
문제 2:
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);
}
}
- A) abc
- B) b
- C) 아무 것도 출력되지 않음
- D) 컴파일 에러
정답: B) b
해설: filter 연산으로 "b"와 일치하는 요소만을 선택한 후 출력한다. 따라서 "b"만 출력된다.
문제 3:
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);
}
}
- A) 14916
- B) 1234
- C) 149
- D) 컴파일 에러
정답: C) 149
해설: IntStream.range(1, 5)는 1, 2, 3, 4 값을 포함하는 스트림을 만든다. map(x -> x * x)는 각 값을 제곱하여 출력한다. 1^2 = 1, 2^2 = 4, 3^2 = 9, 4^2 = 16이므로 출력은 "149"이다.
문제 4:
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"));
}
}
- A) Lambda
- B) Default
- C) 컴파일 에러
- D) 아무 것도 출력되지 않음
정답: A) Lambda
해설: Optional.of("Lambda")는 Lambda라는 값을 포함하는 Optional 객체를 생성한다. orElse는 값이 존재할 경우 그 값을 반환하므로 "Lambda"가 출력된다.
문제 5:
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);
}
}
- A) ABC
- B) B
- C) C
- D) 아무 것도 출력되지 않음
정답: B) B
해설: filter 연산은 문자열이 "B"로 시작하는지 여부를 확인하고, "B"만 필터링하여 출력한다.
코테
브2
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int[] inputs = new int[8];
for (int i = 0; i < inputs.length; i++) inputs[i] = sc.nextInt();
sc.close();
String output = "";
for (int i = 0; i < inputs.length - 1; i++) {
if (inputs[i] == inputs[i + 1] - 1) output = "ascending";
else if (inputs[i] == inputs[i + 1] + 1) output = "descending";
else {
output = "mixed";
break;
}
}
System.out.println(output);
}
}
브1
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
while(true) {
String S = br.readLine();
StringBuilder sb = new StringBuilder(S);
String Sreverse = sb.reverse().toString();
if(S.equals("0")) break;
if(S.equals(Sreverse)) {
System.out.println("yes");
}else{
System.out.println("no");
}
}
}
}