# EffectiveJava

114개의 포스트

다 쓴 객체 참조를 해제하라_item7

※ 메모리 누수는 겉으로 잘 드러나지 않아 시스템에 수년간 잠복하는 사례도 있다. 이런 누수는 철저한 코드 리뷰나 합 프로파일러 같은 디버깅 도구를 동원해야만 발견되기도 한다. 그래서 이런 종류의 문제는 예방법을 익혀두는 것이 매우 중요하다.

약 6시간 전
·
0개의 댓글
·
post-thumbnail

[Effective_Java] Item 1 : 생성자 대신 정적 팩터리 메서드를 고려하라.

🔥들어가며... 개발자라면 혹은 개발자를 꿈꾼다면 한 번 쯤은 들어봤을 그 책! Effective Java를 읽고 공부하며 정리하는 느낌으로 글을 쓰려 합니다. 어렵다고 소문이 나 있지만, 일단 때려 박아보는게 맞지 않겠습니까 하하😂 날카로운 지적은 언제든 환영입니다 :) 그럼 Item 90까지 달리는 그 날을 향해 시작해봅시다! 생성자 대신 정적 팩터리 메서드를 고려하라. 클라이언트가 클래스의 인스턴스를 얻는 전통적인 수단은 public 생성자 입니다. 하지만 이와 별도로 정적 팩토리 메서드(Static factory method)를 사용하는 방법이 있습니다. 들어가기 전에, 과연 정적 팩토리 메서드가 무엇일까요? 정적 팩토리 메서드(Static Factory Method)란? 정적 팩토리 메서드는 > 해당 클래스의 인스턴스를 반환하는 단순한 정적 메서드 입니다. 쉽게 말해서, >객체 생성의 역할을 하는 클래스 메서드 인 것이죠. 자

5일 전
·
0개의 댓글
·

불필요한 객체 생성을 피하라_item6

똑같은 기능이 객체를 매번 생성하기보다는 객체 하나를 재사용하는 편이 낫다. 또한 생성자 대신 정적 팩터리 메서드를 사용하는 것이 좋다. 생성자는 호출할 때마다 새로운 객체를 만들지만, 팩터리 메서드는 전혀 그렇지 않다. 이 메서드가 내부에서 만드는 정규표현식용 Pattern인스턴스는, 한 번 쓰고 버려져서 곧바로 가비지 컬렉션 대상이 된다. 성능이 중요한 상황에서 반복해 사용하기엔 적합하지 않다. 필요한 정규표현식을 표현하는 (불변인)Pattern 인스턴스를 클래스 초기화(정적 초기화) 과정에서 직접 생성해 캐싱해두고, 나중에 isRomanNumeral 메서드가 호출될 때마다 이 인스턴스를 재사용하는 코드이다. 물론 isRomanNumeral 클래스가 초기화 된 후 메서드를 한번도 호출하지 않는다면 ROMAN필드는 쓸데없이 초기화된 꼴이다. 장점 불변인 인스턴스를 재사용하기에 안전함과 성능 개선 staitc final 필드

6일 전
·
0개의 댓글
·

자원을 직접 명시하지 말고 의존 객체 주입을 사용하라_item5

사용하는 자원에 따라 동작이 달라지는 클래스에는 정적 유틸리티 클래스나 싱글턴 방식이 적합하지 않다. 때문에 의존 객체 주입의 한 형태로, 인스턴스를 생성할 때 생성자에 필요한 자원을 넘겨주는 방식을 사용하는 것이 좋다. 변형으로 생성자에 자원 팩터리를 넘겨주는 방식이 있다. > 팩터리란? 호출할 때마다 특정 타입의 인스턴스를 반복해서 만들어주는 객체를 말한다. 팩터리 메서드 패턴을 구현 하자. 일반적으로 한정적 와일드 카드 타입을 사용해 팩터리의 타입 매개변수룰 제한하면 명시한 타입의 하위 타입이라면 무엇이든 생성할 수 있는 팩터리를 넘길 수 있게 된다. > ※클래스가 내부적으로 하나 이상의 자원에 의존하고, 그 자원이 클래스 동작에 영향을 준다면 싱글턴과 정적 유틸리티 클래스는 사용하지 않는 것이 좋다. 이 자원들을 클래스가 직접 만들게 해서도 안 된다. 대신 필요한 자우너을 (혹은 그 자원을 만들어주는 팩토리를)생성자에 (혹은 정적 팩터리나

6일 전
·
0개의 댓글
·

인스턴스화를 막으려거든 private 생성자를 사용하라_item4

단순히 정적 메서드와 정적 필드만을 담은 클래스를 만들때 생성자를 명시하지 않으면 컴파일러가 자동으로 기본 생성자를 만들어 준다. (추상 클래스로 만드는 것으로는 인스턴스화를 막을 수 없다. -> 하위 클래스를 만들어 인스턴스화) 인스턴스화를 막는 방법 private 생성자를 추가하면 클래스의 인스턴스화를 막을 수 있다. 명시적 생성자가 private이니 클래스 바깥에서는 접근할 수 없으며 상속 또한 불가능 하다 클래스 안에서 실수로라도 생성자를 호출하지 않도록 Assertion Error를 던질 수 있다.

2023년 9월 13일
·
0개의 댓글
·

private 생성자나 열거 타입으로 싱글턴임을 보증_item3

싱글톤을 만드는 방식 싱글톤 : 인스턴스를 오직 하나만 생성할 수 있는 클래스 public static final 필드 방식 protectd or public 생성자가 없으므로 public static final 필드를 초기화할 때 딱 한번만 호출한다. 그러나 리플렉션 때문에 두 번째 객체가 생성될때 예외를 던지게 해야한다. > #### 리플렉션 API 구체적인 클래스 타입을 알지 못하더라도 그 클래스의 메서드,타입,변수들에 접근할 수 있도록 해주는 자바 API이며 권한이 있는 클라이언트는 리플렉션 API를 사용해 private 생성자 호출가능하다. 장점 싱글톤임이 API에 명백히 드러난다.(public static 필드가 final이니 절대로 다른 객체를 참조할 수 없다.) 간결하다. 정적 팩토리 방식의 싱글턴 항상 같은 객체의 참조를 반환하므로 제2의 Elvis 인스턴스는 만들어지지 않는다. (똑같이 리플렉션을 통한 예외 적

2023년 9월 13일
·
0개의 댓글
·

정적 팩터리 메서드_item1

정적 팩터리 메서드 클래스는 클라이언트에 public 생성자 대신(혹은 생성자와 함께) 정적 팩터리 메서드를 제공할 수 있다. 장점 이름을 가질 수 있다.(생성자에 비해 객체 특성 설명 가능) 호출될 대마다 인스턴스를 새로 생성하지는 않아도 된다. 반환 타입의 하위 타입 객체를 반환할 수 있는 능력이 있다. 입력 매개변수에 따라 매번 다른 클래스의 객체를 반환할 수 있다. 정적 팩터리 메서드를 작성하는 시점에는 반환할 객체의 클래스가 존재하지 않아도 된다. 단점 상속을 하려면 public이나 protected 생성자가 필요하니 정적 팩터리 메서드만 제공하면 하위 클래스를 만들 수 없다. 정적 팩터리 메서드는 프로그래머가 찾기 어렵다.(API 문서를 잘 써놓고 메서드 이름도 널리 알려진 규약을 따라 짓는 식으로 문제를 완화해줘야 한다.) > #### ※ 정적 팩터리 메서드와 public 생성자는 각자의 쓰임새가 있으니 상대적인 장단점을

2023년 9월 7일
·
0개의 댓글
·
post-thumbnail

[Effective Java] Item 1 : 생성자 대신 정적 팩터리 메서드를 고려하라

전통적인 클래스 인스턴스를 반환하도록 하는 방법은 public 생성자 하지만 아래와 같은 정적 팩터리 메서드 방식을 고려해야 한다. 클래스의 인스턴스를 반환하는 단순한 static 메서드 static factory method가 생성자에 비해 가지는 장점 이름을 가질 수 있다 위 예시의 valueOf함수와 같이 다양한 이름을 설정 가능 호출될 때 마다 인스턴스를 새로 생성하지는 않아도 된다. 불필요한 객체의 생성을 막을 수 있음. 인스턴스의 통제가 가능 싱글턴 패턴 구현가능 인스턴스화 불가 등 인스턴스가 단 하나임을 보장할 수 있도록 할 수 있음 반환 타입의 하위 타입 객체를 반환할 수 있는 능력이 있다.

2023년 1월 25일
·
0개의 댓글
·
post-thumbnail

[Java] Stream with EffectiveJava 45~47

EffectiveJava 45~47 stream 사용시 주의사항 서론 > 최근 Java8 feature들에 대해서 다시 한번 공부하면서 Stream 까지 포스팅을 하게 되었는데Effective Java 역시 최근 다시 한번 복습하고 있기에 최근 본 Stream에 관한 부분에 대한 부분들을 정리하여 포스팅해두려고 합니다. > 병렬 처리에 대한 item48은 따로 몇 가지 다른 정보들과 합쳐서 추가적으로 포스팅할 예정이며 이 글은 45~47까지의 item을 정리하여 적어 두려고 합니다. Effective Java에서의 조언(Item 45 ~ 47)정리 Stream은 주의해서 사용하라. (Item 45) Stream을 과용하는 것을 피하자 프로그램이 읽거나 유지 보수하기 어려워 진다 아나그램 예시 아나그램(anagram) : 알파벳이 같고 순서만 다른 단어를 말한다. ex) stap

2023년 1월 6일
·
0개의 댓글
·
post-thumbnail

빌더 (Builder) 패턴

1. 패턴 소개 제품을 여러 단계로 나눠서 만들 수 있도록 제품 생산 단계들을 캡슐화하고 싶다면 빌더패턴을 사용하면 됩니다. 아래는 여행계획을 기록할 인스턴스들 입니다. 여행계획에 대한 정보를 기록할 TourPlan클래스 세부적인 일정을 기록할 DetailPlan클래스 TourPlan, DetailPlan인스턴스를 생성하여 여행계획을 세우는 Client 코드 위의 TourPlan, DetailPlan의 인스턴스를 생성하여 아래와 같이 여행 계획을 세우는 코드가 있습니다. 보시면 상당히 장황하다는 것을 알 수 있습니다. 객체 하나를 만들려면 메서드를 여러 개 호출해야 하고, 객체가 완전히 생성되기 전까지는 일관성이 무너진 상태에 놓이게 됩니다. 이렇게 되면 반드시 설정해

2022년 12월 6일
·
0개의 댓글
·

아이템 33. 타입 안전 이종 컨테이너를 고려하라

우리가 생각하는 컨테이너는 어떤 다른 객체를 넣을 수 있는 또다른 객체를 생각할 수 있습니다. 가령 Set, Map, Optional 이런것들이 객체를 넣을 수 있는 컨테이너라고 할 수 있는데 우리가 여태까지 사용했던 제네릭을 사용하는 방식은 아래 Favorites클래스처럼 오로지 딱 한가지 타입만을 넣을 수 있는방식이었습니다. 하지만 위와 같이 하나의 타입으로만 요소를 넣지 않고 여러가지 타입을 저장하고 싶을때 아래와 같이 Map을 참조해서 구현할 수 있습니다.

2022년 11월 26일
·
0개의 댓글
·

아이템 32. 제네릭과 가변인수를 함께 쓸 때는 신중하라

가변인수란 클라이언트의 입장에서 파라미터를 몇개 보낼지 선택할 수 있는 변수를 말합니다. 아래에 dangerous메서드의 인자에 ...이렇게 점이 세개가 있는데 이것을 가변인수를 받을수 있다는것을 의미합니다. 제네릭타입의 가변인수를 받는 dangerous메서드 문제는 제네릭타입과 같이쓰면 문제가 생깁니다. 제네릭은 성격상 배열과 맞지 않고 배열보다는 리스트를 사용하도록 아이템 28에서 다루었습니다. 배열은 공변이고 실체화가 되지만 제네릭은 불공변이고 실체화가 되지 않기때문에 같이 쓸때 문제가 생긴다고 했습니다. 컴파일러는 이러한 선언을 허용하지 않습니다. 하지만 내부적으로는 제네릭의 배열이 만들어지는 경우가 있습니다. 가변인자와 제네릭타입을 같이 쓰면 내부적으로 배열을 생성합니다. 그래서 직접 선언해서 제네릭 타입의 배열을 만들 순 없지만 가변인자를 사용하면 자바 내부적으로는 배열을 만드는것이 가능합니다. 위의 dangerous메서드의 가변인자는 컴파일에러는 아니

2022년 11월 25일
·
0개의 댓글
·

아이템 30. 이왕이면 제네릭 메서드로 만들라

매개변수화 타입을 받는 정적 유틸리티 메서드 제네릭 메서드를 사용하면 컴파일 타임에 타입안정성을 보장할 수 있습니다. 제네릭을 사용하지 않는 메서드 Union클래스에 union이라는 메소드가 있는데 전혀 제네릭타입을 쓰고 있지 않습니다. 위와 같이 두개의 Set을 union메서드를 통해서 하나로 합치는데에는 타입이 다르다 하더라도 문제가 없습니다. 문제는 꺼내서 쓸 때인데 둘 중에 한가지의 타입을 예측해서 예를들면 String타입으로 나온다고 가정하고 사용한다면 문제가 됩니다. 위와같이 String타입으로 for문을 실행할 경우 integer타입으로 저장된 요소를 호출할때 ClassCastException이 터집니다. 이런문제를 컴파일 타임에 방지를 하려면 아래와 같은 제네릭 타입을 적용해서 구현하면 됩니다. 제네릭을 사용한 union메서드 제네릭을 사용한 union을 사용해서 다른 타입의 Set을 하나로 합치려고하면 컴파일타임에 에러가 발

2022년 11월 22일
·
0개의 댓글
·

아이템 29. 이왕이면 제네릭 타입으로 만들라

어떤 클래스를 만들다 보면 클래스안에 어떤 다른 객체를 담는 역할을하는 클래스를 만들 수 있습니다. 예를 들어 스택이라는 자료구조안에 어떤 Element들을 쌓는경우가 생기는데 이런경우 보통 제네릭타입으로 만들면 유용합니다. 특히 Object타입으로 담고있다면 더더욱 명확하게 제네릭을 사용해서 더 구체적인 타입으로 코딩을 하도록 유도하면 런타임시에 ClassCastException을 많이 줄여줄 수 있습니다. Object를 이용한 제네릭 스택 위에 구현한 스택은 Object타입으로 요소들을 받고 있기 때문에 아래와 같이 pop을 할때 Object타입이기 때문에 넣어줬던 타입에 맞게 강제로 타입캐스팅을 해야합니다. 이렇게 강제 타입캐스팅을 하면 String타입이 아니고 다른 타입을 넣었을경우 ClassCastException이 일어날 수 있습니다. 이런 경우를 미연에 방지하기 위해 제네릭으로 스택을 구현하는게 좋은데 2가지 방법이 있습니다. E[]를 이용한 제

2022년 11월 21일
·
0개의 댓글
·

아이템 28. 배열보다는 리스트를 사용하라

1. 배열은 공변(covariant), 제네릭은 불공변 anything배열을 보면 오른쪽 타입은 Object배열이고 왼쪽은 String타입입니다. Object와 String의 상속관계는 String이 Object를 상속하고 있습니다. 따라서 String타입을 Object타입으로 변환이 가능합니다. 하지만 제네릭은 불공변 입니다. anything은 Object배열 타입을 참조하고는 있지만 실제 인스턴스는 String의 배열입니다. 하지만 이 부분이 아무 문제 없어보이지만 분명히 문제가 있는 코드입니다. anything이라고 참조하고 있는 배열은 문자열의 배열입니다. 그럼에도 불구하고 위와같이 숫자를 넣는거는 잘못된 코딩입니다. 하지만 List는 String의 List를 Object의 리스트로 참조할 수 없습니다. 이 둘은 그냥 다른타입 입니다. 따라서 컴파일시점에 오류가 납니다. 이것이 불공변입니다. 2. 배열은 실체화(reify) 되지만, 제네릭은 실체화 되지 않는

2022년 11월 20일
·
0개의 댓글
·

아이템 25. 톱 레벨 클래스는 한 파일에 하나만 담으라

톱레벨 클래스라는 것은 파일에 정의되어있는 가장 바깥에 있는 클래스를 의미합니다. 가장 바깥에 있는 클래스가 여러개 있어도 컴파일하는데 문제는 없습니다. 하지만 한파일에는 톱레벨 클래스를 오직 하나만 선언하길 권장하고 있습니다. 그 이유는 한 파일에 톱 레벨 클래스가 여러개가 있다면 컴파일을 어떻게 하느냐에 따라서 결과가 달라질 수 있습니다. 어떤 클래스가 다른클래스에 종속적이라면 아이템24의 정적 멤버클래스를 사용하면 가독성도 좋고 private접근 지시자를 사용해서 클래스의 접근범위를 최소화 할 수 있습니다. 정적 멤버클래스로 선언

2022년 11월 18일
·
0개의 댓글
·

아이템 24. 멤버 클래스는 되도록 static으로 만들라

OutterClass내부의 정적 멤버 클래스 InnerClass는 OutterClass의 내부에 있는 static 멤버 클래스 입니다. static 멤버 클래스인 InnerClass의 특징은 number와 같은 바깥에 있는 정적 필드에 접근을 할 수 있습니다. 또한 바깥클래스인 OutterClass를 필요로 하지 않고 독립적입니다. OutterClass필요없이 InnerClass인스턴스를 단독으로 사용이 가능합니다. 이런 static 멤버 클래스는 바깥클래스인 OutterClass를 거쳐서 쓰기 용이한 클래스를 정의할때 static 멤버 클래스로 선언합니다. OutterClass내부의 비정적 멤버 클래스 비정적 멤버 클래스인 InnerClass는 암묵적으로 OutterClass의 인스턴스에 대한 참조가 생깁니다. 그 뜻은 OutterClass의 인스턴스 없이는 InnerClass인스턴스를 생성할 수 없다는 뜻입니다. 그래서 InnerClass인스턴스를

2022년 11월 18일
·
0개의 댓글
·
post-thumbnail

[Effective Java 스터디 week4] [ITEM 22]인터페이스는 타입을 정의하는 용도로만 사용하라

[ITEM 22]인터페이스는 타입을 정의하는 용도로만 사용하라 자바의 인터페이스 인터페이스는 자신을 구현한 클래스의 인스턴스를 참조할 수 있는 타입 역할만 하는데, 오직 이 용도로만 사용해야 한다. 상수 인터페이스라는 안티패턴이 있는데, 절대 사용하지말라고 한다. 상수 인터페이스 안티패턴은 인터페이스를 잘못 사용한 예이다. 클래스 내부에서 사용하는 상수는 외부 인터페이스가 아닌 내부 구현에 해당하기에 상수 인터페이스를 구현하는 것은 내부 구현을 클래스의 API로 노출하는 행위이다. 자바 플랫폼 라이브러리에서도 잘못활용한 예니까 따라하지마세요! 상수 인터페이스 안티패턴을 사용하지 않고 상수를 공개하는 방법 박싱클래스처럼 열거타입으로 만들어 공개 인스턴스화 할 수 없는 유틸리티 클래스에 담아 공개 유틸리티클래스에 정의된 상수를 클라이언트에서 사용하려면 클래스 이름까지 명시해야하는데, Static Import를 사용하면 변수명으로만 사

2022년 11월 18일
·
0개의 댓글
·
post-thumbnail

[Effective Java 스터디 week3] [ITEM 15] 클래스와 멤버의 접근 권한을 최소화하라

[ITEM 15] 클래스와 멤버의 접근 권한을 최소화하라 어설프게 설계된 컴포넌트와 잘 설계된 컴포넌트의 가장 큰 차이 클래스 내부 데이터와 내부 구현 정보를 외부 컴포넌트로부터 얼마나 잘 숨겼는가. 오직 API를 통해서만 다른 컴포넌트와 소통하며, 서로의 내부 동작 방식에는 전혀 개의치 않는다. 정보 은닉, 캡슐화 라고 한다. 캡슐화의 장점! 시스템 개발 속도를 높인다. 여러 컴포넌트를 병렬로 개발할 수 있기 때문. 시스템 관리 비용을 낮춘다. 각 컴포넌트를 더 빨리 파악하여 디버깅 가능 다른 컴포넌트로 교체하는 부담을 줄여줌 정보 은닉 자체가 성능을 높여주지는 않지만 성능 최적화에 도움을 준다. 완성된 시스템을 프로파일링해 최적화할 컴포넌트를 정한 다음 다른 컴포넌트에 영향을 주지 않고 해당 컴포넌트만 최적화할 수 있기 때문이다. 소프트웨어 재사용성을 높

2022년 11월 18일
·
0개의 댓글
·
post-thumbnail

[Effective Java 스터디 week2] [ITEM 8]finalizer와 cleaner 사용을 피하라

[ITEM 8]finalizer와 cleaner 사용을 피하라 자바는 두 가지 객체 소멸자를 제공 finalizer는 예측할 수 없고, 상황에 따라 위험할 수 있다 기본적으로 쓰지말아야 한다. 자바9 부터는 deprecated 대안으로 cleaner가 생겼지만 이것도 쓰면 안됨 이 책에서는 try-with-resource와 try-finally를 사용하여 해결한다. finalizer와 cleaner로는 제때 실행되어야 하는 작업을 절대 할 수 없고 언제 실행될지는 전적으로 GC 알고리즘에 달려있다. 프로그램 생애주기와 상관없는, 상태를 영구적으로 수정하는 작업에서는 절대 finalizer나 cleaner에 의존하면 안됨 ex) DB connection close같은것 잡지 못한 예외로 인해 불완전한 객체가 남아있을 수 있으며 어떻게 동작할지 예측 불가능하다. finalizer에서 일어난 예외는 출력되지 않는다. 성능이슈까지 있다. AutoCloseable을 구현하고

2022년 11월 18일
·
0개의 댓글
·