일단 이것저것 해 보는 블로그

(Do it! 자바, 5주차) 내부 클래스와 관련 개념(람다식, 스트림) (260202~260208) 본문

2026/Do it Java 스터디(2026.01.~02.)

(Do it! 자바, 5주차) 내부 클래스와 관련 개념(람다식, 스트림) (260202~260208)

뷔구룽 2026. 2. 2. 14:37

개요

비전공자인 나에게 조금씩 벽을 드러내고 있는 자바.

처음부터 이 많은 걸 다 이해해야 되는지, 앞으로 어떻게 자바를 활용해야 할지 여러모로 고민이 많았던 한 주였다.

(+ 곧 있을 정보처리기사 필기 준비와, 만성 게으름으로 심적으로도 고생 많이 함 ㅎㅎㅎㅎㅎ;;)

 

사용한 학습 자료: 박은종, 2025, <Do it! 자바 프로그래밍 입문 [개정판]>, 이지스퍼블리싱.

https://ebook-product.kyobobook.co.kr/dig/epd/ebook/E000010942415

 

Do it! 자바 프로그래밍 입문 [개정판] | 박은종 저자

eBook Do it! 자바 프로그래밍 입문 [개정판] | 3만 6천 부 이상 팔린 초판의 성공에 힘입어 좀 더 입문자의 눈높이에 맞춰 내용을 수정하고 최신 개발 트렌드에 맞게 개정판을 출간했습니다. 저자인

ebook-product.kyobobook.co.kr

 

5주차 공부 인증

 

공부한 내용 정리

<12장: 컬렉션 프레임워크>

https://gyeonkangkim.tistory.com/25

(4주차에 정리 완료)

 

(Do it! 자바, 4주차) JDK 기본 클래스와 컬렉션 프레임워크 (260126~260130)

개요4주차는, 자바 개발 환경에서 기본적으로 제공되는 클래스와 함께프로그래밍 더 나아가 컴퓨터 과학의 기초가 된다는 자료 구조와 관련이 깊은 컬렉션 프레임워크가 등장한다.이제는 자바

gyeonkangkim.tistory.com

 

<13장: 내부 클래스, 람다식, 스트림>

1) 내부 클래스(중첩된 클래스): 명칭 그대로 클래스 안의 클래스

 

(478쪽: 내부 클래스 유형과 특징)

종류 구현 위치 사용 가능한 외부 클래스 변수 만드는 방법
인스턴스 내부 클래스 외부 클래스의 인스턴스 변수와 같은 위치 외부 인스턴스 변수
외부 정적 변수
먼저 만든 외부 클래스 안에 생성
정적 내부 클래스 외부 클래스 인스턴스 변수와 같은 위치 외부 정적 변수 외부 클래스와 무관하게 생성
지역 내부 클래스 메서드 내부에서만 외부 인스턴스 변수
외부 정적 변수
메서드 호출 시 생성
익명 내부 클래스
(이름을 사용하지 않고 바로 정의)
메서드 내부
변수에 대입해 직접 구현
외부 인스턴스 변수
외부 정적 변수
1) 메서드 호출 시 생성
2) 인터페이스 자료형 변수에 대입 시 new 예약어 사용해 생성

 

(472쪽: 정적 내부 클래스에 구현되는 메서드 비교 정리)

정적 내부 클래스 메서드 변수 유형 사용 가능 여부
일반 메서드 외부 클래스 인스턴스 변수 불가
외부 클래스 정적 변수 가능
정적 내부 클래스 인스턴스 변수 가능
정적 내부 클래스 정적 변수 가능
정적(static) 메서드 외부 클래스 인스턴스 변수 불가
외부 클래스 정적 변수 가능
정적 내부 클래스 인스턴스 변수 불가
정적 내부 클래스 정적 변수 가능

 

* 익명 내부 클래스는 주로 어디에 사용할까?(477쪽): 안드로이드 앱 프로그래밍에서 위젯의 이벤트를 처리하는 이벤트 핸들러 구현에 사용.

- 위젯: 안드로이드에서 사용하는 버튼과 텍스트 상자 등.

- 이벤트 핸들러: 사용자가 위젯을 사용할 때 발생하는 이벤트를 처리하는 코드

 

2) 람다식(Lambda): 자바에서 지원하는 함수형 프로그래밍.

-> 함수형 프로그래밍이란? 함수를 구현하고 호출하는 것만으로 프로그램을 만들 수 있다!

(매개변수) -> {구체적인 실행문;}
// 매개변수를 활용해 실행문 내용대로 실행해라.
// 함수의 이름을 쓰지 않는 익명 함수

 

(람다식 주요 문법)

// 함수의 매개변수 자료형 생략하고 사용 가능
V = {System.out.println(V);}
// 매개변수가 두 개 이상이면 반드시 괄호 붙이기
(V, Vnum) = {System.out.println(V + Vnum);}
// 함수의 실행문이 한 문장일 때, 중괄호 생략 가능
V = System.out.println(V);
// 실행문이 return 문이면 반드시 중괄호 붙이기
V = {return V.height();}
// 실행문이 return문 하나면 중괄호와 return 모두 생략
V = V.height()

 

람다식 구현: 주로 인터페이스를 만든 다음 그 인터페이스에 람다식으로 구현할 메서드를 선언만 함(함수형 인터페이스).

// 함수형 인터페이스 선언
@FunctionalInterface // '나 함수형 인터페이스다'라고 알리는 애너테이션
public interface MinNumber {
	int getMin(a, b) // 람다식 구현할 추상 메서드 선언만
}

// 테스트 프로그램
// 두 수 중 최솟값 출력
public class TestMinNumber {
	public static void main(String[] args) {
    	MinNumber min = (a, b) -> (a <= b) ? a : b; // 인터페이스형 변수 min에 람다식(함수) 구현
        System.out.println(min.getMin(10, 30)); // min에서 메서드 호출
    }
}

 

* 람다식으로 구현할 함수형 인터페이스에는 반드시 하나의 메서드만!

람다식은 이름 없는 함수이기에 메서드가 여러 개면 어떤 걸 구현할 지 헷갈리기 때문

 

(일반적인 객체지향 프로그래밍(OOP)와 람다식의 차이)

// 일반적인 객체지향 프로그래밍 예시

// 인터페이스
public interface StringConcat {
	void NewconCat(String s1, String s2); // 두 문자열을 합치는 추상 메서드
}

// 인터페이스를 구현하는 클래스
public class StringConcatImplements implements StringConcat {
	@Override
    void NewConcat(String s1, String s2) {
    	System.out.println(s1 + s2); // 메서드 구현
    }
}

// 테스트 프로그램
public class TestStringConcat {
	public static void main(String[] args) {
    	String s1 = "뷔구룽 ";
        String s2 = "is learning Java Programming."
    	StringConcatImplements str = new StringConcatImplements(); // 인터페이스형 변수에 객체를 대입하고
        str.NewConcat(s1, s2); // 인터페이스형 변수에서 메서드 호출
    }
}

 

위 코드를 람다식을 사용해 더 간결하게 작성할 수 있음.

// 람다식 활용 예

// 인터페이스
@FunctionalInterface
public interface StringConcat {
	void NewconCat(String s1, String s2); // 두 문자열을 합치는 추상 메서드
}

// 테스트 프로그램
public class TestStringConcat {
	public static void main(String[] args) {
    	String s1 = "뷔구룽 ";
        String s2 = "is learning Java Programming."
        // 별도의 구현 클래스 없이 바로 인터페이스를 구현해 호출할 수 있음.
    	StringConcat str2 = (s, v) -> System.out.println(s + v);
        str2.StringConcat(s1, s2);
    }
}

 

3) 스트림: 배열 정렬 기준을 정하는 등 여러 자료를 처리하는 기능 구현한 클래스

-> 자료 추상화: 여러 자료를 일관적으로 처리할 수 있음.

 

(사용 예)

package stream;

import java.util.Arrays;
// 정수 배열과 스트림
public class IntArrayTest {
    public static void main(String[] args) {
        int[] arr = {1, 2, 3, 4, 5};

        int max = (int) Arrays.stream(arr).max().getAsInt(); // 요소 중 최댓값
        int min = (int) Arrays.stream(arr).min().getAsInt(); // 요소 중 최솟값
        double avg = Arrays.stream(arr).average().getAsDouble(); // 배열 요소 평균

        System.out.println(max);
        System.out.println(min);
        System.out.println(avg);
    }
}

 

* 추가 참고(스트림의 연산 메서드/집계 메서드): 잇트루, [Java] 자바 스트림 생성과 중간 연산, 최종 연산의 개념 정리 및 활용,
https://ittrue.tistory.com/165#google_vignette (260204 최종접속)

 

[Java] 자바 스트림 생성과 중간 연산, 최종 연산의 개념 정리 및 활용

스트림 자바의 스트림은 데이터를 연속적으로 전달하는 통로로 표현할 수 있다. 스트림(Stream)은 다양한 데이터 소스(배열, 컬렉션)를 표준화하여 다루는 방식으로 통합된 방식으로 데이터 핸들

ittrue.tistory.com

 

- 스트림 연산: 자료 처리에 필요한 연산 기능을 메서드로 제공

중간 연산: 자료 필터링, 변형 -> 내부에서 또 다른 자료 생성

최종 연산: 생성된 내부 자료의 요소를 하나씩 순회하며(Iteration) 소모 -> 연산 수행

-> 마지막에 한 번만

 

(추후 보충 필요: 498쪽 Distinct 연산부터 되새김 문제까지)

 

<14장: 예외 처리>

프로그램(소프트웨어)이 갑자기 튕기거나 오류가 발생해 사용이 어려워진다면 곤란할 것.

이때, 오류가 발생할 때마다 프로그램이 갑자기 멈추지 않도록 매끄럽게 처리하는 게 바로 예외 처리!

 

1) 오류와 예외 클래스

- 코드 작성 시 실수로 일어나는 컴파일 오류는 개발 환경에서 대개 원인을 찾아 잡을 수 있다(컴파일러가 대부분 원인이나 솔루션을 잘 알려줌).

하지만 의도치 않게 프로그램이 중지되거나 의도 밖으로 실행되는 실행 오류(혹은 버그)는 예외가 많이 존재해 잡아내기 힘들다. 게다가 이런 실행 오류로 프로그램이 비정상 종료되는 일이 잦아진다면 큰 사고가 될 수 있다.

- 이때 프로그램 오류 원인을 잘 남겨놓은 로그 분석과, 적절한 오류 처리가 예기치 못한 오류 관리에 많은 도움이 된다.

 

* 실행 오류의 종류

- 시스템 오류: 자바 가상 머신에서 발생하며 주로 메모리 문제(사용 가능한 동적 메모리 없음, 오버플로 등)에서 기인함. 프로그램에서 제어할 수 없음. -> Throwable 클래스를 상속받은 Error 클래스

- 예외: 자바에서 제공하는 클래스를 적절히 활용해 제어할 수 있음.

-> Throwable 클래스를 상속받은 Exception 클래스

 

** Exception 클래스

- 프로그램에서 처리하는 예외 클래스 중 최상위

- 주요 하위 클래스: IOException(입출력 예외), RuntimeExceptio되n(실행 중 오류에 대한 예외)

=> 예외에는 확인 예외와 확인되지 않은 예외가 있다.

확인 에외는 컴파일러에서 확인 가능하므로 반드시 예외 처리 코드를 명기해 주어햐 한다(그렇지 않으면 컴파일 오류 발생).

-> try~catch문, throws 등

확인되지 않은 예외는 별도로 처리해주지 않아도 컴파일 오류가 발생하지 않음. 따라서 코드 작성 시 주의 필요.

 

2) 예외 처리: 예외 상황 자체를 막을 수 있는 먼치킨은 아니지만, 예외 상황을 정확히 알려주고 프로그램의 비정상 종료를 막아주므로 유용함.

- try~catch문

// try~catch문 예시

int a = 5;
int b = 0;

try {
	// 예외가 발생할 수 있는 코드 부분
    System.out.println(a / b) // 5를 0으로 나눌 수 없으므로 오류 발생
} catch(연산 오류에 대한 예외 e) {
	// 예외 발생 시 어떻게 예외를 처리할지 작성
    System.out.println("정수는 0으로 나눌 수 없음!")
}

 

- try~catch~finally문: try 블록이 수행되면 finally 블록이 항상 수행됨. 

// try~catch~finally문 예시

int a = 5;
int b = 0;

try {
	// 예외가 발생할 수 있는 코드 부분
    System.out.println(a / b) // 5를 0으로 나눌 수 없으므로 오류 발생
} catch(연산 오류에 대한 예외 e) {
	// 예외 발생 시 어떻게 예외를 처리할지 작성
    System.out.println("정수는 0으로 나눌 수 없음!")
} finally {
	System.out.println("항상 수행되는 문장")
	}

 

(14장 되새김 문제: 완성)

https://gyeonkangkim.tistory.com/32

 

(Do it! 자바, 5주차-1) 14장 되새김 문제 풀이(작성 중)

사용한 학습 자료: 박은종, 2025, , 이지스퍼블리싱.https://ebook-product.kyobobook.co.kr/dig/epd/ebook/E000010942415 Do it! 자바 프로그래밍 입문 [개정판] | 박은종 저자eBook Do it! 자바 프로그래밍 입문 [개정판] |

gyeonkangkim.tistory.com

 

새롭게 배운 점(어려웠던 점)

- 이번 주말(일요일)에 정보처리기사 필기 시험이 있을 예정이라, 책의 예제를 보다 꼼꼼하게 실습해보지는 못했다.

두 가지 공부를 같이 할 때 우선순위를 적절히 세팅하는 게 쉽지 않았다.

그래도 일단은 필기에 합격하는 게 우선이라, 이번 주에는 자바 스터디 학습 비중을 많이 줄였다.

 

- 이번 주 분량에서는 유독 생소한 메서드나 코드가 많았고(스트림과 예외 처리 등), 책에서는 이에 대한 설명이 많이 부족함을 느꼈다.

일단 최대한 따라해보며 눈으로 익혀두기는 했지만, 각 기능을 어디에 어떻게 활용해야할 지는 아직 잘 모르겠다.

우선 완독하고 추후 더 공부하거나 프로젝트를 진행할 때 기능이 필요해지면 그때 더 찾아 활용해보는 것도 좋을 것 같다.

 

실습 코드(깃허브)

https://github.com/KimGyeonkang/DoitJava_Studying_2026

 

GitHub - KimGyeonkang/DoitJava_Studying_2026

Contribute to KimGyeonkang/DoitJava_Studying_2026 development by creating an account on GitHub.

github.com