Develop Artifacts/Java

Java - 13. stream

Stream 파이프라인에서 filter가 호출되지 않는 순간 — 지연 평가의 작동 원리list.stream() .filter(x -> { System.out.println("filter: " + x); return x > 5; }) .map(x -> { System.out.println("map: " + x); return x * 2; }) .findFirst();이 코드를 실행하면 전체 리스트를 순회하며 모든 요소에 filter와 map을 적용할까? — 아니다. 첫 번째로 조건을 만족하는 요소를 찾는 즉시 중단된다. findFirst()가 단 하나의 결과만 필요하므로, Stream은 그것만 계산한다. 이것이 지연 평가(lazy evaluation)다. (Stream API)지연 평가가 ..

Develop Artifacts/Java

Java - 11. generics

List과 List가 런타임에 같은 타입인 이유 — 제네릭과 타입 소거new ArrayList().getClass() == new ArrayList().getClass() — 이 표현식은 true다. List과 List는 런타임에 같은 클래스(ArrayList)다. 제네릭 타입 정보가 컴파일 후 사라지기 때문이다 — 이것이 타입 소거(type erasure)다. (JLS §4.6)타입 소거를 모르면, 리플렉션으로 제네릭 타입을 검사하려다 실패하고, 제네릭 배열을 만들려다 컴파일 에러를 만나고, 힙 오염(heap pollution)에 빠진다. 왜 Java는 이렇게 설계했을까? 이 글은 제네릭이 컴파일 후 어떻게 사라지는지, 그리고 와일드카드(PECS)로 무엇을 하는지 풀어간다.제네릭이 해결하는 문제 — 타..

Develop Artifacts/Java

Java - 10. collections

HashMap에서 7개의 키가 충돌하면 어떤 일이 일어나는가 — 컬렉션 선택의 기준HashMap에 7개의 키를 넣었다. 버킷 하나에 8번째 충돌이 발생하는 순간, 내부 데이터 구조가 연결 리스트에서 레드블랙 트리로 바뀐다. (HashMap JavaDoc) 대부분의 개발자는 이 사실을 모른 채 HashMap을 쓴다. 그래야 할까? — 대부분의 경우 그래도 된다. 하지만 성능이 갑자기 저하되거나, 메모리가 예상보다 많이 쓰일 때, 이 내부 구조를 아는 것이 문제 해결의 열쇠가 된다.왜 ArrayList는 0.001초인데 LinkedList는 1초 걸릴까? 정답은 "메모리에 어떻게 배치되어 있는가"에 있다. 이 글은 List, Set, Map, Queue 각각이 내부적으로 어떻게 동작하는지를 풀어간다.컬렉션 ..

Develop Artifacts/Java

Java - 09. exception

throws Exception이 최악의 예외 처리인 이유 — 예외 계층과 자원 관리메서드 시그니처에 throws Exception이라고 적힌 코드를 본 적이 있는가. "뭔가 예외가 날 수 있는데, 구체적으로 뭔지는 모르겠고, 어차피 호출하는 쪽에서 처리해"라는 뜻이다. 이것은 예외 처리가 아니라 예외 무시다. 호출하는 쪽은 catch (Exception e)를 강제받고, 정작 복구할 수 있는 정보는 없다."복구할 수 있으면 checked, 못 하면 unchecked." — 이 한 문장이 Java 예외 시스템의 핵심이다. (JLS §11) 이 글은 checked vs unchecked의 선택 기준, try-with-resources의 자동 자원 관리, 그리고 "예외를 삼키면 안 되는 이유"를 풀어간다.예외..

Develop Artifacts/Java

Java - 08. record sealed enum

보일러플레이트를 없앤 Java의 세 가지 타입 — record, sealed, enumPoint 클래스를 만든다고 하자. x, y 필드, 생성자, getter, equals, hashCode, toString — Java에서 불변 데이터 객체 하나를 제대로 만들려면 50줄이 필요했다. Lombok @Value로 줄여봤지만, 그것은 서드파티 라이브러리에 대한 의존이었다.Java 16에 record가 들어왔다. public record Point(double x, double y) {} — 한 줄. 컴파일러가 나머지를 다 만들어 준다. (JEP-395) 왜 Java는 30년이나 지나서야 이 한 줄을 가능하게 했을까? 이 글은 record, sealed, enum 세 가지 현대 타입이 기존 코드를 어떻게 바꾸..

Develop Artifacts/Java

Java - 07. interface and abstract

interface에 메서드 본문이 들어간 이유 — default method와 다중 구현의 충돌Java 8 이전의 interface는 순수한 명세였다 — 메서드 선언만 있고 본문이 없는 계약서. 그런데 라이브러리를 배포했는데, 나중에 새 메서드를 추가해야 한다면? 그 인터페이스를 구현한 모든 클래스가 컴파일 에러로 깨진다. 이 문제를 해결하기 위해 default method가 도입됐다 — interface에 본문이 있는 메서드를 넣을 수 있게 됐다. (JEP-126, Java 8) "이미 구현체를 가진 메서드를 interface에 넣을 수 있다"는 작은 변화가, Java 컬렉션 API 전체에 함수형 프로그래밍을 가능하게 했다.하지만 두 interface가 같은 이름의 default method를 가지면 ..

Archive

'Java' 24

Develop Artifacts/Java

Java - 13. stream

Stream 파이프라인에서 filter가 호출되지 않는 순간 — 지연 평가의 작동 원리list.stream() .filter(x -> { System.out.println("filter: " + x); return x > 5; }) .map(x -> { System.out.println("map: " + x); return x * 2; }) .findFirst();이 코드를 실행하면 전체 리스트를 순회하며 모든 요소에 filter와 map을 적용할까? — 아니다. 첫 번째로 조건을 만족하는 요소를 찾는 즉시 중단된다. findFirst()가 단 하나의 결과만 필요하므로, Stream은 그것만 계산한다. 이것이 지연 평가(lazy evaluation)다. (Stream API)지연 평가가 ..

댓글
Develop Artifacts/Java

Java - 11. generics

List과 List가 런타임에 같은 타입인 이유 — 제네릭과 타입 소거new ArrayList().getClass() == new ArrayList().getClass() — 이 표현식은 true다. List과 List는 런타임에 같은 클래스(ArrayList)다. 제네릭 타입 정보가 컴파일 후 사라지기 때문이다 — 이것이 타입 소거(type erasure)다. (JLS §4.6)타입 소거를 모르면, 리플렉션으로 제네릭 타입을 검사하려다 실패하고, 제네릭 배열을 만들려다 컴파일 에러를 만나고, 힙 오염(heap pollution)에 빠진다. 왜 Java는 이렇게 설계했을까? 이 글은 제네릭이 컴파일 후 어떻게 사라지는지, 그리고 와일드카드(PECS)로 무엇을 하는지 풀어간다.제네릭이 해결하는 문제 — 타..

댓글
Develop Artifacts/Java

Java - 10. collections

HashMap에서 7개의 키가 충돌하면 어떤 일이 일어나는가 — 컬렉션 선택의 기준HashMap에 7개의 키를 넣었다. 버킷 하나에 8번째 충돌이 발생하는 순간, 내부 데이터 구조가 연결 리스트에서 레드블랙 트리로 바뀐다. (HashMap JavaDoc) 대부분의 개발자는 이 사실을 모른 채 HashMap을 쓴다. 그래야 할까? — 대부분의 경우 그래도 된다. 하지만 성능이 갑자기 저하되거나, 메모리가 예상보다 많이 쓰일 때, 이 내부 구조를 아는 것이 문제 해결의 열쇠가 된다.왜 ArrayList는 0.001초인데 LinkedList는 1초 걸릴까? 정답은 "메모리에 어떻게 배치되어 있는가"에 있다. 이 글은 List, Set, Map, Queue 각각이 내부적으로 어떻게 동작하는지를 풀어간다.컬렉션 ..

댓글
Develop Artifacts/Java

Java - 09. exception

throws Exception이 최악의 예외 처리인 이유 — 예외 계층과 자원 관리메서드 시그니처에 throws Exception이라고 적힌 코드를 본 적이 있는가. "뭔가 예외가 날 수 있는데, 구체적으로 뭔지는 모르겠고, 어차피 호출하는 쪽에서 처리해"라는 뜻이다. 이것은 예외 처리가 아니라 예외 무시다. 호출하는 쪽은 catch (Exception e)를 강제받고, 정작 복구할 수 있는 정보는 없다."복구할 수 있으면 checked, 못 하면 unchecked." — 이 한 문장이 Java 예외 시스템의 핵심이다. (JLS §11) 이 글은 checked vs unchecked의 선택 기준, try-with-resources의 자동 자원 관리, 그리고 "예외를 삼키면 안 되는 이유"를 풀어간다.예외..

댓글
Develop Artifacts/Java

Java - 08. record sealed enum

보일러플레이트를 없앤 Java의 세 가지 타입 — record, sealed, enumPoint 클래스를 만든다고 하자. x, y 필드, 생성자, getter, equals, hashCode, toString — Java에서 불변 데이터 객체 하나를 제대로 만들려면 50줄이 필요했다. Lombok @Value로 줄여봤지만, 그것은 서드파티 라이브러리에 대한 의존이었다.Java 16에 record가 들어왔다. public record Point(double x, double y) {} — 한 줄. 컴파일러가 나머지를 다 만들어 준다. (JEP-395) 왜 Java는 30년이나 지나서야 이 한 줄을 가능하게 했을까? 이 글은 record, sealed, enum 세 가지 현대 타입이 기존 코드를 어떻게 바꾸..

댓글
Develop Artifacts/Java

Java - 07. interface and abstract

interface에 메서드 본문이 들어간 이유 — default method와 다중 구현의 충돌Java 8 이전의 interface는 순수한 명세였다 — 메서드 선언만 있고 본문이 없는 계약서. 그런데 라이브러리를 배포했는데, 나중에 새 메서드를 추가해야 한다면? 그 인터페이스를 구현한 모든 클래스가 컴파일 에러로 깨진다. 이 문제를 해결하기 위해 default method가 도입됐다 — interface에 본문이 있는 메서드를 넣을 수 있게 됐다. (JEP-126, Java 8) "이미 구현체를 가진 메서드를 interface에 넣을 수 있다"는 작은 변화가, Java 컬렉션 API 전체에 함수형 프로그래밍을 가능하게 했다.하지만 두 interface가 같은 이름의 default method를 가지면 ..

댓글

wall

방명록

방문 흔적을 남겨주세요. 질문이나 인사 모두 환영합니다.