티스토리 뷰
📖 람다
Java 8부터 도입된 표현식으로 메서드처럼 별도의 이름을 가질 필요 없이(익명 함수) 한 줄의 표현으로 함수를 정의 하고 사용할 수 있다. 람다는 코드의 간결성을 높이고, 병렬 처리와 같은 기능을 보다 쉽게 구현하도록 한다.
// 기존의 익명 클래스 방식
Runnable r1 = new Runnable() {
@Override
public void run() {
System.out.println("Hello, World!");
}
};
// 람다 표현식을 사용한 방식
Runnable r2 = () -> System.out.println("Hello, World!");
람다가 생긴 이유
자바는 객체지향 언어지만, 코드가 길고 반복되는 경우가 많아 가독성이 떨어지는 문제가 있었다. 특히, 익명 클래스를 사용해야 하는 상황(이벤트 리스너, 스레드 실행 등)에서 불필요한 코드가 많아지는 단점이 있었다.
람다 표현식은 이러한 문제를 해결하기 위해 메서드를 간결하게 표현하는 함수형 스타일을 도입하여 코드의 가독성을 높이고, 유지보수를 쉽게 만들기 위해 생겨났다.
📖 스트림
스트림은 Java 8부터 도입된 데이터 처리 방식으로, 컬렉션(배열, 리스트 등)의 데이터를 필터링, 매핑 등 다양한 방식으로 처리할 수 있도록 지원한다. 스트림을 사용하면 병렬 처리와 같은 작업을 손쉽게 수행할 수 있다.
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class StreamExample {
public static void main(String[] args) {
List<String> names = Arrays.asList("John", "Jane", "Jack", "Doe");
List<String> filteredNames = names.stream()
.filter(name -> name.startsWith("J"))
.collect(Collectors.toList());
System.out.println(filteredNames); // [John, Jane, Jack]
}
}
스트림이 생긴 이유
기존의 for문이나 Iterator를 사용하여 데이터를 처리할 때, 코드가 길어지고 데이터 타입마다 다른 방식으로 다뤄야 하는 불편함이 있었다.
스트림은 이러한 문제를 해결하기 위해 데이터 소스를 추상화하여 컬렉션(List, Set)이나 배열을 같은 방식으로 처리할 수 있도록 설계되었다. 이를 통해 코드를 더 직관적이고 간결하게 작성할 수 있으며, 병렬 처리도 가능해졌다.
📖 어노테이션이란?
어노테이션은 자바 소스코드에 추가하는 메타데이터로, 자체적으로 실행되지는 않지만 컴파일 타임이나 런타임에 특정 기능을 수행하도록 영향을 미치는 역할을 한다. 클래스, 인터페이스, 메서드, 파라미터 등에 적용 가능하다.
class Parent {
void display() {
System.out.println("Parent 클래스");
}
}
class Child extends Parent {
@Override // 부모의 메서드를 올바르게 오버라이드했는지 체크
void display() {
System.out.println("Child 클래스");
}
}
어노테이션 사용 이유
- 어노테이션 자체는 실행되지 않지만, 리플렉션을 통해 실행 중에 어노테이션 정보를 읽고 특정 로직을 수행할 수 있다.
- 컴파일 타임에는 코드에 추가적인 의미를 부여하고, 런타임에는 리플렉션을 활용해 어노테이션을 읽고 동적으로 동작을 변경할 수 있다.
- 대표적인 예로 Spring의 @Autowired 어노테이션이 있다.
📖 리플렉션이란?
- 구체적인 클래스 타입을 알지 못하더라도 그 클래스의 메서드, 타입, 변수들에 접근할 수 있도록 해주는 자바 API
- 컴파일 시간이 아닌 실행 시간에 동적으로 특정 클래스의 정보를 추출할 수 있는 프로그래밍 기법이다.
- 작성 시점에는 어떠한 클래스를 사용해야 할지 모르지만, 런타임 시점에서 클래스를 가져와서 실행해야 하는 경우에 필요하다.
💡 추가: System.out.println() 클래스의 성능
System.out.println() 내부 구조 분석
public void println(String x) {
synchronized (this) {
print(x);
newLine();
}
}
✔️ println() 내부에서 synchronized가 사용되어 동기화 처리됨
✔️ 하나의 스레드만 실행할 수 있고, 다른 스레드는 실행이 끝날 때까지 대기해야 함
성능 저하의 원인
✅ synchronized로 인해 멀티스레드 환경에서 병목(Bottleneck) 발생
- 여러 스레드가 동시에 System.out.println()을 호출하면, 한 번에 하나의 스레드만 접근 가능
- 다른 스레드는 출력이 끝날 때까지 대기 상태(Blocked)가 되어 오버헤드 발생
✅ I/O 작업 자체가 느림
- System.out.println()은 콘솔 출력(Console I/O)을 수행하는데, 콘솔 출력은 일반적인 연산보다 상대적으로 속도가 느린 작업
- 디스크나 네트워크와 비교할 정도는 아니지만, CPU 연산보다는 속도가 느림
'Study > CS 스터디 - Java' 카테고리의 다른 글
동시성 (0) | 2025.04.03 |
---|---|
Thread (0) | 2025.03.27 |
컬렉션 (0) | 2025.03.27 |
문자열, 예외, 제네릭 (0) | 2025.03.19 |
자바 기본 & 객체 지향 (0) | 2025.03.13 |