Effective Java - 아이템 25: 로 타입은 사용하지 말라
제네릭 클래스와 인터페이스 선언에 타입 매개변수(type parameter)가 쓰이면, 이를 제네릭 클래스 혹은 제네릭 인터페이스라 한다. 제네릭 클래스와 제네릭 인터페이스를 통틀어 제네릭 타입(generic type)이라 한다.
제네릭 클래스와 인터페이스 선언에 타입 매개변수(type parameter)가 쓰이면, 이를 제네릭 클래스 혹은 제네릭 인터페이스라 한다. 제네릭 클래스와 제네릭 인터페이스를 통틀어 제네릭 타입(generic type)이라 한다.
중첩 클래스(nested class)란 다른 클래스 안에 정의된 클래스를 말한다. 중첩 클래스는 자신을 감싼 바깥 클래스에서만 쓰여야 하며, 그 외의 쓰임새가 있다면 톱레벨 클래스로 만들어야 한다. 중첩 클래스의 종류는 정적 멤버 클래스, (비정적) 멤버 클래스, 익명 클래스, ...
```java // 태그 달린 클래스 - 클래스 계층구조보다 훨씬 나쁘다 class Figure { enum Shape { RECTANGLE, CIRCLE }; // 태그 필드 - 현재 모양을 나타낸다. final Shape shape; // 다음 필드들은 모양이 사각형...
인터페이스의 인터페이스는 자신을 구현한 클래스의 인스턴스를 참조할 수 있는 타입 역할을 한다. 달리 말해, 클래스가 어떤 인터페이스를 구현한다는 것은 자신의 인스턴스로 무엇을 할 수 있는지를 클라이언트에 얘기해주는 것이다. 인터페이스는 오직 이 용도로만 사용해야 한다.
디폴트 메서드 디폴트 메서드(default method)를 선언하면, 그 인터페이스를 구현한 후 디폴트 메서드를 재정의하지 않은 모든 클래스에서 디폴트 구현이 쓰이게 된다. 디폴트 메서드는 구현 클래스에 대해 아무것도 모른 채 합의 없이 무작정 ‘삽입’될 뿐이다. 그로인해 생각할 ...
자바가 제공하는 다중 구현 메커니즘은 인터페이스와 추상 클래스, 이렇게 두 가지다. 자바 8부터 인터페이스도 디폴트 메서드(default method)를 제공할 수 있게 되어 이제는 두 메커니즘 모두 인스턴스 메서드를 구현 형태로 제공할 수 있다.
상속을 고려한 설계와 문서화란?
메서드 호출과 달리 상속은 캡슐화를 깨뜨린다. 상위 클래스가 어떻게 구현되느냐에 따라 상속하는 하위 클래스의 동작에 이상이 생길 수 있다. 상위 클래스는 릴리스마다 내부 구현이 달라질 수 있기 때문에, 코드 한 줄 수정하지 않은 하위 클래스에서 오동작 할 수 있다.
```java // 퇴보한 public 클래스 class Point { public double x; public double y; } // 데이터 필드에 직접 접근할 수 있으니 캡슐화의 이점을 제공하지 못한다. // API를 수정하지 않고는 내부 표현을 바꿀 수 없...
compareTo Comparable 인터페이스의 유일한 메서드인 compareTo는 단순 동치성 비교에 더해 순서까지 비교할 수 있으며, 제네릭하다. Comparable을 구현했다는 것은 그 클래스의 인스턴스들에는 자연적인 순서(natural order)가 있음을 뜻한다.
Cloneable은 복제해도 되는 클래스임을 명시하는 용도의 믹스인 인터페이스(mixin interface)지만, 의도한 목적을 제대로 이루지 못했다.
Object의 기본 toString은 PhoneNumber@adbbd 처럼 단순히 {클래스이름}@{16진수}로 표시한 해시코드를 반환할 뿐이다. toString의 일반 규약에 따르면 간결하면서 사람이 읽기 쉬운 형태의 유익한 정보를 반환해야 한다.
equals를 재정의한 클래스 모두에서 hashCode도 재정의해야 한다 재정의하지 않으면 일반 규약을 어기게 되어 HashMap, HashSet 같은 컬렉션의 원소로 사용할 때 문제를 일으킬 것이다.
equals를 재정의하지 않는 것이 좋은 상황 각 인스턴스가 본질적으로 고유하다. 값을 표현하는게 아니라 동작하는 개체를 표현하는 클래스. Thread가 좋은 예 인스턴스의 ‘논리적 동치성(logical equality)’을 검사할 일이 ...
try-finally 전통적으로 예외가 발생하거나 메서드에서 반환되는 경우를 포함해 자원이 제대로 닫힘을 보장하는 수단으로 try-finally가 쓰였다. // 더 이상 자원을 회수하는 최선의 방책이 아니다. static String firstLineOfFile(String pat...
자바는 두 가지 객체 소멸자를 제공한다. finalizer는 예측할 수 없고, 상황에 따라 위험할 수 있어 일반적으로 불필요하다. 그래서 기본적으로 쓰지 말아야 한다. finalizer의 대안으로 나온cleaner는 finalizer보다는 덜 위험하지만, 여전히 예측할 수 없고,...
메모리 누수가 있는 프로그램을 오래 실행하다 보면 점차 가비지 컬렉션 활동과 메모리 사용량이 늘어나 결국 성능이 저하된다.
기존 객체를 재사용해야 한다면 새로운 객체를 만들지 마라 똑같은 기능의 객체를 매번 생성하기보다 불변 객체처럼 재사용하는 편이 낫다.
// 정적 유틸리티를 잘못 사용한 예 - 유연하지 않고 테스트하기 어렵다. public class SpellChecker { private static final Lexicon dictionary = ...; private SpellChecker() {} /...
정적 멤버만 담은 유틸리티 클래스는 인스턴스로 만들어 쓰려고 설계한게 아니다. 하지만 생성자를 명시하지 않으면(직접 작성한 생성자가 하나도 없는 경우) 컴파일러가 자동으로 기본 생성자를 만들어준다. 사용자는 이 생성자가 자동 생성된 것인지 구분할 수 없다. // 인스턴스로 만들 의...
싱글턴(Singleton)
빌더패턴 이전에 사용하던 방식
정적 팩터리 메서드 new키워드로 생성하지 않고 객체 생성해서 반환하는 메서드다.
요약 유사한 성격의 메일을 발송하는 두 클래스를 추상 클래스를 선언하고 템플릿 메서드 패턴을 사용하여 공통 로직을 한 곳으로 모아서 중복을 제거했습니다.
요약 다양한 캐싱 전략 중에서 로컬 캐시를 선택하여 오전 7시에 RDS에 집중된 조회 작업으로 인한 부하를 줄였습니다. 기존 코드는 카테고리별 질문지(백엔드, 프론트엔드)를 구독자 수 만큼 반복적으로 질문 테이블에서 대량의 데이터를 조회하고 있었는데, 이런 비효율을 해결했습니...
요약 구독자별 받은 질문지 모아보기 기능을 구현하는데 있어서 기존 테이블 관계를 파악하고 추가적인 다대다 테이블을 설계하였습니다. 그 과정에 현재 운영 상황과 스키마 변경 비용을 고려하여 테이블 정규화를 고민했습니다.
요약 비동기 스레드 풀의 대기 큐 사이즈보다 더 많은 요청이 들어와서 발생한 TaskRejectedExceptoin 에러와, AWS SES 초당 요청 처리 제한 초과로 인해 발생한 SMTPSendFailedExceptioin 에러가 발생하여 해결했습니다. 바로 조치하여 해결할...
사용자 추적을 위한 조회 기능 개발
4번 문제
3번 문제
토미의 트랜잭션, 인덱스 강의 자료를 학습하여 작성했다.
얼마 전 우테코의 코치 토미가 인덱스 강의를 해주셨다. 아마 토미가 미리 만들어두신 것으로 추정되는 백만에 가까운 row가 들어있는 대용량의 데이터를 바탕으로 강의가 진행되었다. 원래 수업시간 외에 크루들에게 데이터를 제공할 계획이 없으셨으나, 무수한 백엔드 크루들의 성원에 못이기...
org.hibernate.HibernateException: A collection with cascade=”all-delete-orphan” was no longer referenced by the owning entity instance 에러 트러블 슈팅한 내용이다.
정산을 위해 지출 내용을 직접 입력해야 된다는 것 자체가 엄청나게 큰 허들.
우아한테크코스 6기 레벨3에는 팀 프로젝트를 진행하는데, 내가 속한 팀은 행동대장 팀이다.
4번 문제
3번 문제
토미의 트랜잭션, 인덱스 강의 자료를 학습하여 작성했다.
isValidDuplicated 메서드는 친구관계를 나타내는 friends 리스트에서 [[”json”, “john”], [”john”, “json”]] 과 같이 중복되는 친구관계가 담겨있는지 확인하는 메서드이다. ```java // 개선 전 // friend는 [[“json”, ...
// 개선 전 // friend는 [["json", "john"], ["john", "mike"]...] 이런 데이터가 담긴 List이다. private static Map<String, List<String>> makeFriendRelation(List<...
isValidDuplicated 메서드는 친구관계를 나타내는 friends 리스트에서 [[”json”, “john”], [”john”, “json”]] 과 같이 중복되는 친구관계가 담겨있는지 확인하는 메서드이다. ```java // 개선 전 // friend는 [[“json”, ...
// 개선 전 // friend는 [["json", "john"], ["john", "mike"]...] 이런 데이터가 담긴 List이다. private static Map<String, List<String>> makeFriendRelation(List<...
학점을 구하는 방법 = (교과목 학점 + 평점)의 합 / 수강신청 총 학점 수.
리팩토링 전 코드는 크게 두 가지 기능으로 영화관에서 관람객이 티켓을 구매하거나 초대권을 사용하여 입장, 카페에서 고객이 캐셔에게 음료 주문을 하여 바리스타가 주문을 바탕으로 음료를 만들어주는 기능을 하는 코드였다. 하지만 기능이 동작하는 것과 별개로 각 객체들이 너무 많은 범위의...
학점을 구하는 방법 = (교과목 학점 + 평점)의 합 / 수강신청 총 학점 수.
리팩토링 전 코드는 크게 두 가지 기능으로 영화관에서 관람객이 티켓을 구매하거나 초대권을 사용하여 입장, 카페에서 고객이 캐셔에게 음료 주문을 하여 바리스타가 주문을 바탕으로 음료를 만들어주는 기능을 하는 코드였다. 하지만 기능이 동작하는 것과 별개로 각 객체들이 너무 많은 범위의...
리팩토링 전 코드는 크게 두 가지 기능으로 영화관에서 관람객이 티켓을 구매하거나 초대권을 사용하여 입장, 카페에서 고객이 캐셔에게 음료 주문을 하여 바리스타가 주문을 바탕으로 음료를 만들어주는 기능을 하는 코드였다. 하지만 기능이 동작하는 것과 별개로 각 객체들이 너무 많은 범위의...
학점을 구하는 방법 = (교과목 학점 + 평점)의 합 / 수강신청 총 학점 수.
학점을 구하는 방법 = (교과목 학점 + 평점)의 합 / 수강신청 총 학점 수.
@ParameterizedTest
@ParameterizedTest
private static List<String> WORDS = Arrays.asList("TONY", "a", "hULK", "B", "america", "X", "nebula", "Korea"); // List에 저장된 단어들 중에서 단어의 길이가 2 이상인...
private static List<String> WORDS = Arrays.asList("TONY", "a", "hULK", "B", "america", "X", "nebula", "Korea"); // List에 저장된 단어들 중에서 단어의 길이가 2 이상인...
표준 입력과 출력을 테스트하는 방법은 여러 가지가 있지만, 이 코드에서는 System.setIn(InputStream)과 System.setOut(PrintStream)을 이용하여 표준 입력과 출력을 변경한다.
표준 입력과 출력을 테스트하는 방법은 여러 가지가 있지만, 이 코드에서는 System.setIn(InputStream)과 System.setOut(PrintStream)을 이용하여 표준 입력과 출력을 변경한다.
EnumMap은 Java에서 제공하는 Map 인터페이스 구현체 중 하나다.
EnumMap은 Java에서 제공하는 Map 인터페이스 구현체 중 하나다.
Functional Interface는 함수를 일급객체처럼 다룰 수 있게 해주는 단 하나의 추상 메서드를 가지는 인터페이스이다. final 상수나 default, static, private 메서드는 추상 메서드가 아니기 때문에, 이들 여러개가 인터페이스에 들어있어도 단 한 개의 ...
Functional Interface는 함수를 일급객체처럼 다룰 수 있게 해주는 단 하나의 추상 메서드를 가지는 인터페이스이다. final 상수나 default, static, private 메서드는 추상 메서드가 아니기 때문에, 이들 여러개가 인터페이스에 들어있어도 단 한 개의 ...
방어적 복사
방어적 복사
방어적 복사
```java public class Person { private List favoriteFoods;
```java public class Person { private List favoriteFoods;
동작 파라미터화(behavior parameterization)를 이용하면 자주 바뀌는 요구사항에 효과적으로 대응할 수 있다. 동작 파라미터화란 아직은 어떻게 실행할 것인지 결정하지 않은 코드 블록을 의미한다. 이 코드 블록은 나중에 프로그램에서 호출한다. 즉, 코드 블록의 실행은...
람다 표현식은 메서드로 전달할 수 있는 익명 함수를 단순화한 것이라고 할 수 있다. 익명: 보통의 메서드와 달리 이름이 없으므로 익명이라 표현한다. 함수: 람다는 메서드처럼 특정 클래스에 종속되지 않으므로 함수라 한다. 하지만 메서드처럼 파라미터 리스트, 바디, 반환 형식...
처음으로 참가한 대회 Pinely Round 4 (Div. 1 + Div. 2)
얼마 전 우테코의 코치 토미가 인덱스 강의를 해주셨다. 아마 토미가 미리 만들어두신 것으로 추정되는 백만에 가까운 row가 들어있는 대용량의 데이터를 바탕으로 강의가 진행되었다. 원래 수업시간 외에 크루들에게 데이터를 제공할 계획이 없으셨으나, 무수한 백엔드 크루들의 성원에 못이기...
얼마 전 우테코의 코치 토미가 인덱스 강의를 해주셨다. 아마 토미가 미리 만들어두신 것으로 추정되는 백만에 가까운 row가 들어있는 대용량의 데이터를 바탕으로 강의가 진행되었다. 원래 수업시간 외에 크루들에게 데이터를 제공할 계획이 없으셨으나, 무수한 백엔드 크루들의 성원에 못이기...
얼마 전 우테코의 코치 토미가 인덱스 강의를 해주셨다. 아마 토미가 미리 만들어두신 것으로 추정되는 백만에 가까운 row가 들어있는 대용량의 데이터를 바탕으로 강의가 진행되었다. 원래 수업시간 외에 크루들에게 데이터를 제공할 계획이 없으셨으나, 무수한 백엔드 크루들의 성원에 못이기...
org.hibernate.HibernateException: A collection with cascade=”all-delete-orphan” was no longer referenced by the owning entity instance 에러 트러블 슈팅한 내용이다.
사용성이 좋지 않다는 사용자 피드백에 따라 비즈니스 로직 개선
사용성이 좋지 않다는 사용자 피드백에 따라 비즈니스 로직 개선