Java 19

Effective Java Item86. Serializable을 구현할지는 신중히 결정하라.

직렬화는 쉽다. implements Serializable만 붙이면 된다.Serializable을 구현하면 릴리스한 뒤에는 수정하기 어렵다. 클래스가 Serializable을 구현하면 직렬화된 바이트 스트림 인코딩도 하나의 공개 API가 된다. 이 클래스가 널리 퍼진다면 그 직렬화 형태도 영원히 지원해야한다.기본 직렬화 형태에서는 클래스의 private과 package-private 인스턴스 필드들마저 API로 공개되는 꼴이 된다.(캡슐화가 깨진다). 필드로의 접근을 최대한 막아 정보를 은닉하라는 조언도 무력화된다.직렬화 가능 클래스를 만들고자 하면, 길게 보고 감당할 수 있을 만큼 고품질의 직렬화 형태도 주의해서 함께 설계해야 한다. 직렬화 설계 시 주의 사항스트림 고유 식별자, serialVersio..

Java/EffectiveJava 2025.03.23

Effective Java Item85. 자바 직렬화의 대안을 찾으라.

자바 직렬화분산 객체를 만들 수 있다는 구호보이지 않는 생성자, API와 구현 사이의 모호해진 경계, 잠재적인 정확성 문제, 성능, 보안, 유지보수성 등 대가가 컸다.직렬화의 근본적인 문제공격 범위가 너무 넓고 지속적으로 더 넓어져 방어하기 어렵다.ObjectInputStream의 readObject 메서드를 호출하면서 객체 그래프가 역직렬화되기 때문이다.readObject 메서드는 클래스패스 안의 거의 모든 타입의 객체를 만들어 낼 수 있는 생성자다.바이트 스트림을 역직렬화하는 과정에서 이 메서드는 그 타입들 안의 모든 코드를 수행할 수 있다.코드 전체가 공격 범위에 들어간다.모든 직렬화 가능 클래스들을 공격에 대비하도록 작성한다해도 취약하다.역직렬화에 시간이 오래 걸리는 짧은 스트림을 역직렬화하는 것..

Java/EffectiveJava 2025.03.23

Effective Java Item80. 스레드보다는 실행자, 태스크, 스트림을 애용하라.

작업 큐를 손수 만드는 일은 삼가야 하고, 스레드를 직접 다루는 것도 일반적으로 삼가야 한다. 실행자 프레임워크를 사용하여 작업 단위와 실행 단위로 이용하자.실행 단위ExecutorService(실행서비스)특정 태스크가 완료되기를 기다린다.태스크 모음 중 아무것 하나 혹은 모든 태스크가 완료되기를 기다린다.실행자 서비스가 종료하기를 기다린다.완료된 태스크들의 결과를 차례로 받는다.태스크를 특정 시간에 혹은 주기적으로 실행하게 한다.큐를 둘 이상의 스레드가 처리하게 하고 싶다면 간단히 다른 정적 팩터리를 이용하여 다른 종류의 실행자 서비스(스레드 풀)를 생성하면 된다. 스레드 풀의 스레드 개수는 고정할 수도 있고 필요에 따라 늘어나거나 줄어들게 설정할 수도 있다. ThreadPoolExecutor 스레드 ..

Java/EffectiveJava 2025.03.16

Effective Java Item79. 과도한 동기화는 피하라.

과한 동기화는 성능을 떨어뜨리고, 교착상태에 빠뜨리고, 심지어 예측할 수 없는 동작을 낳기도 한다.응답 불가와 안전 실패를 피하려면 동기화 메서드나 동기화 블록 안에서는 제어를 절대로 클라이언트에 양도하면 안 된다. 동기화된 영역을 포함한 클래스 관점에서는 재정의 함수나, 함수 객체 모두 포함된다.이 경우 메서드 호출을 동기화 블록 바깥으로 옮기면 된다.CopyOnWriteArrayList 사용 : ArrayList를 구현한 클래스로, 내부를 변경하는 자업은 항상 깨끗한 복사본을 만들어 수행하도록 구현했다.내부의 배열은 절대 수정되지 않으니 순회할 때 락이 필요 없어 매우 빠르다.수정할 일은 드믈고 순회만 빈번히 일어나는 관찰자 리스트 용도로 최적이다.열린 호출(OpenCall)private void n..

Java/EffectiveJava 2025.03.16

Effective Java Item68. 일반적으로 통용되는 명명 규칙을 따르라.

자바 플랫폼은 명명 규칙이 잘 정립되어 있으며, 그중 많은 것으로 자바 언어 명세에 기술되어 있다. 자바의 명명 규칙은 크게 철자와 문법, 두 범주로 나뉜다.철자 규칙패키지, 클래스, 인터페이스, 메서드, 필드, 타입 변수의 이름을 다룬다.패키지와 모듈 이름은 각 요소를 점으로 구분하여 계층적으로 짓는다.패키지 이름의 나머지는 해당 패키지를 설명하는 하나 이상의 요소로 이뤄진다.8자 이하의 짦은 단어로 해야한다.인터넷 도메인 이름 뒤에 요소 하나만 붙인 패키지가 많지만, 많은 기능을 제공하는 경우엔 계층을 나눠 더 많은 요소로 구성해도 좋다.클래스와 인터페이스의 이름은 하나 이상의 단어로 이뤄지며, 각 단어는 대문자로 시작한다.첫 글자만 딴 약자나 max, min처럼 널리 통용되는 줄임말을 제외하고는 ..

Java/EffectiveJava 2025.03.09

Effective Java Item67. 최적화는 신중히 하라.

그 어떤 핑계보다 효율성이라는 이름 아래 행해진 컴퓨팅 최악이 더 많다. - 윌리엄 울프자그마한 효율성은 모두 잊자. 섣부른 최적화가 만악의 근원이다. - 도널드 크누스최적화를 할 때는 다음 두 규칙을 따르라. 첫번째 하지 마라. 두 번째 아직 하지 마라. 다시 말해 명백하고 최적화되지 않은 해법을 찾을 때까지는 하지 마라. - M.A 잭슨빠른 프로그램보다는 좋은 프로그램을 작성하라.좋은 프로그램이지만 원하는 성능이 나오지 않는다면 그 아키텍처 자체가 최적화할 수 있는 길을 안내해줄 것이다.좋은 프로그램은 정보 은닉 원칙을 따르므로 개별 구성요소의 내부를 독립적으로 설계할 수 있다. 즉, 시스템의 나머지에 영향을 주지 않고도 각 요소를 다시 설계할 수 있다.완성된 설계의 기본 틀을 변경하려다 보면 유지보..

Java/EffectiveJava 2025.03.09

Effective Java Item54. null이 아닌, 빈 컬렉션이나 배열을 반환하라.

null이 아닌, 빈 배열이나 컬렉션을 반환하라. null을 반환하는 API는 사용하기 어렵고 오료 처리 코드도 늘어난다. 그렇다고 성능이 좋은 것도 아니다.컬렉션을 반환할 때 빈 컨테이너를 할당하는 데도 비용이 드니 null을 반환하는 쪽이 낫다는 주장이 있다. 하지만 두 가지 면에서 틀린 주장이다.성능 분석 결과 이 할당이 성능 저하의 주범이라고 확인되지 않는 한 이 정도의 성능 차이는 신경 쓸 수준이 못 된다. (item 67)빈 컬렉션과 배열은 굳이 새로 할당하지 않고도 반환할 수 있다.ex) 빈 컬렉션을 반환하는 올바른 예public List getCheeses() { return new ArrayList(cheesesInStock);}사용 패턴에 따라 빈 컬렉션 할당이 성능을 눈에 띄게 떨어..

Java/EffectiveJava 2025.02.22

Effective Java Item53. 가변인수는 신중히 사용하라.

인수 개수가 일정하지 않은 메서드를 정의해야 한다면 가변인수가 반드시 필요하다. 메서드를 정의할 때 필수 매개변수는 가변인수 앞에 두고, 가변인수를 사용할 때는 성능 문제까지 고려하자.가변인수 메서드를 호출하면, 가장 먼저 인수의 개수와 길이가 같은 배열을 만들고 인수들을 이 배열에 저장하여 가변인수 메서드에 건네준다.ex) 간단한 가변인수 활용 예static int sum(int... args) { int sum = 0; for (int arg : args) { sum += arg; } return sum;}ex) 인수가 1개 이상이어 하는 가변인수 메서드 - 잘못 구현한 예static int min(int... args) { if (args.length == 0..

Java/EffectiveJava 2025.02.22

Effective Java Item42. 익명 클래스보다는 람다를 사용하라.

익명 클래스Collections.sort(words, new Comparator() { public int compare(String s1, String s2) { return Integer.compare(s1.length(), s2.length()) }});람다Collections.sort(words, (s1, s2) -> Integer.compare(s1.length(), s2.length()));람다는 함수나 익명 클래스와 개념은 비슷하지만 코드는 훨씬 간결하다. 람다를 사용할 때는 타입을 명시해야하는 코드가 더 명확할 때만 제외하고는, 람다의 모든 매개변수 타입은 생략하자.람다 자리에 비교자 생성 메서드를 사용하면 코드를 더 간결하게 만들 수 있다.Collection..

Java/EffectiveJava 2025.02.16

Effective Java Item41. 정의하려는 것이 타입이라면 마커 인터페이스를 사용하라.

마커 인터페이스(marker interface)? 아무 메서드도 담고 있지 않고, 단지 자신을 구현하는 클래스가 특정 속성을 가짐을 표시해주는 인터페이스 ex) Serializable Serializable은 자신을 구현한 클래스의 인스턴스는 ObjectOutputStream을 통해 쓸 수 있다고, 즉 직렬화 할 수 있다고 알려준다.마커 인터페이스는 구현한 클래스의 인스턴스들을 구분하는 타입으로 쓸 수 있다.자바의 직렬화는 Serializable 마커 인터페이스를 보고 그 대상이 직렬화할 수 있는 타입인지 확인한다.마커 인터페이스는 객체의 특정 부분을 불변식으로 규정하거나, 그 타입의 인스턴스는 다른 클래스의 특정 메서드가 처리할 수 있다는 사실을 명시하는 용도로 사용할 수 있다.즉, 타입을 정의할 거라..

Java/EffectiveJava 2025.02.16