목차
1. Exception
2. 추상 클래스와 인터페이스
3. Stream
예외(Exception)는 프로그램 실행 중 발생할 수 있는 예기치 않은 사건이나 상황을 말합니다.
IOException, FileNotFoundException 등이 있습니다.NullPointerException, ArrayIndexOutOfBoundsException 등이 있습니다.try {
// 예외가 발생할 수 있는 코드
} catch (ExceptionType e) {
// 예외 처리 코드
} finally {
// 예외가 발생하든 안 하든 반드시 실행되는 코드
}
package com.edu.exception.test3;
import java.io.FileReader;
import java.io.IOException;
class FileService4 {
public void readFile(String fileName) throws IOException {
System.out.println("2. FileReader Creating...");
try (FileReader fr = new FileReader(fileName)) { // try-with-resources 구문 사용
System.out.println("3. 파일을 성공적으로 찾았습니다.");
int data;
while ((data = fr.read()) != -1)
System.out.print((char) data);
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
}
public class CompileExceptionTest4 {
public static void main(String[] args) {
System.out.println("1. readFile() calling...");
FileService4 service = new FileService4();
try {
service.readFile("text.txt");
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
}
추상 클래스(Abstract Class)는 완전한 구현을 제공할 수 있는 클래스와 완전한 추상화를 제공하는 클래스의 중간 형태입니다. 추상 클래스는 추상 메소드(구현이 없는 메소드)를 포함할 수 있고, 이 메소드들은 하위 클래스에서 구현해야 합니다.
추상 클래스의 특징
- 추상 메소드를 포함할 수 있다.
- 완전한 메소드 구현도 포함할 수 있다.
- 생성자를 가질 수 있다.
- 상속을 통해 하위 클래스에서 확장할 수 있다.
예시: 추상 클래스 사용
abstract class Animal {
String name;
// 추상 메소드
abstract void sound();
// 일반 메소드
void sleep() {
System.out.println(name + " is sleeping");
}
}
class Dog extends Animal {
Dog(String name) {
this.name = name;
}
@Override
void sound() {
System.out.println(name + " barks");
}
}
인터페이스(Interface)는 모든 메소드가 추상 메소드인 특수한 종류의 클래스입니다. 인터페이스는 클래스가 구현해야 할 메소드의 시그니처를 제공하고, 해당 메소드들의 구현을 강제합니다.
인터페이스의 특징
- 모든 메소드가 기본적으로 추상 메소드이다.
- 다중 상속을 지원한다.
- 상수(필드)는 public static final로 선언된다.
- 추상화 정도가 높다.
interface Animal {
void sound();
void sleep();
}
class Dog implements Animal {
@Override
public void sound() {
System.out.println("Dog barks");
}
@Override
public void sleep() {
System.out.println("Dog sleeps");
}
}
| 항목 | Interface | Abstract Class |
|---|---|---|
| 추상화 수준 | 100% 추상 | 부분 구현 가능 |
| 다중 상속 지원 | 가능 | 불가능 |
| 생성자 | 없음 | 있음 |
| 상속 형태 | implements | extends |
| 사용 목적 | 동작 규약 정의 | 공통 로직 + 추상화 |
Stream은 데이터를 처리하는 일련의 연산을 수행하는 흐름을 의미합니다. Java에서는 Stream API를 통해 데이터를 처리하는 방법을 제공합니다. Stream은 주로 데이터를 필터링, 변환, 집계 등의 작업을 할 때 사용됩니다.
Stream의 흐름
Source (데이터 근원지)에서 데이터를 읽어옵니다.
List, Set, Array
filter(), map(), distinct()collect(), forEach(), reduce()List<String> list = Arrays.asList("a", "b", "c");
list.stream() // Stream 생성
.filter(s -> s.equals("a")) // 중간 연산: 필터링
.forEach(System.out::println); // 최종 연산: 출력
Stream은 데이터를 병렬로 처리할 수 있는 기능을 제공합니다. 예를 들어, 다음과 같이 parallelStream()을 사용하여 데이터를 병렬로 처리할 수 있습니다.
list.parallelStream()
.filter(s -> s.length() > 0)
.forEach(System.out::println);
대규모 데이터나 시간 소모가 큰 연산에서 유용하게 사용할 수 있습니다.
import java.io.FileReader;
import java.io.IOException;
import java.util.stream.Stream;
public class FileService {
public void readFile(String fileName) throws IOException {
try (FileReader fr = new FileReader(fileName)) {
Stream.generate(() -> fr.read()) // Stream을 생성하고 파일을 읽음
.takeWhile(c -> c != -1) // 데이터가 없을 때까지 읽음
.mapToObj(c -> (char) c) // 문자로 변환
.forEach(System.out::print);
}
}
}