전체 글 573

[Effective Java]28.배열보다는 리스트를 사용하라

배열과 제네릭 타입에는 중요한 차이가 두 가지 있다. 첫번째, 배열은 공변이다.(공변 - 함께 변한다는 뜻) Sub가 Super의 하위 타입이라면 배열 Sub[]는 배열 Super[]의 하위 타입이 된다. 반면 제네릭은 불공변이다. 즉, 서로 다른 타입 Type1과 Type2가 있을 때, List은 List의 하위 타입도, 상위 타입도 아니다. 이것만 보면 제네릭에 문제가 있다고 생각할 수 있지만 문제가 있는 건 배열 쪽이다. 배열은 런타임 시점에, 제네릭은 컴파일 시점에 문제를 발견할 수 있기 때문이다. 두번째, 배열은 실체화된다. 배열은 런타임에도 자신이 담기로 한 원소의 타입을 인지하고 확인한다. 그렇기 때문에 런타임 시점에 문제가 발견되는 것이다. 반면에 제네릭은 타입 정보가 런타임에는 소거된다...

Book/Effective Java 2022.07.07

[Effective Java]27.비검사 경고를 제거하라

제네릭을 사용하기 시작하면 수많은 컴파일러 경고를 보게될 것이다. 비검사 형변환 경고, 비검사 메서드 호출 경고, 비검사 매개변수화 가변인수 타입 경고, 비검사 변환 경고 등이다. 대부분의 비검사 경고는 쉽게 제거할 수 있다. 컴파일러가 무엇이 잘못됐는지 설명해주기에 알려준대로 수정하면 경고가 사라진다. 제거하기 훨씬 어려운 경고도 있다. 할 수 있는 한 모든 비검사 경고를 제거해야 한다. 모두 제거한다면 그 코드는 타입 안전성이 보장된다. 즉, 런타임에 ClassCastException이 발생할 일이 없고 의도한 대로 잘 동작하리라 확신할 수 있다. 경고를 제거할 수는 없지만 타입이 안전하다고 확신할 수 있다면 @SuppressWarnings("unchecked") 애너테이션을 달아 경고를 숨겨도 된다..

Book/Effective Java 2022.07.07

[Effective java]26.로 타입은 사용하지 말라

클래스와 인터페이스 선언에 타입 매개변수가 쓰이면 이를 제네릭 클래스, 제네릭 인터페이스라 한다. 예를 들어 List 인터페이스는 원소의 타입을 나타내는 타입 매개변수 E를 받는다. 그래서 이 인터페이스의 완전한 이름은 List지만 짧게 그냥 List라고 쓴다. 제네릭 타입을 하나 정의하면 그에 딸린 로 타입(raw type)도 함께 정의된다. 로 타입이란 제네릭 타입에서 타입 매개변수를 전혀 사용하지 않을 때를 말한다. 예를 들어 List의 로 타입은 List다. 로 타입은 타입 선언에서 제네릭 타입 정보가 전부 지워진 것처럼 동작하는데, 제네릭이 나오기 전 코드와 호환되도록 하기 위한 궁여지책이라 할 수 있다. 오류는 가능한 발생 즉시, 이상적으로는 컴파일할 때 발견하는 것이 좋다. 예를 들어 Lis..

Book/Effective Java 2022.07.07

[2018 카카오 블라인드 1차]추석트래픽

📍 문제 설명 https://school.programmers.co.kr/learn/courses/30/lessons/17676 프로그래머스 코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요. programmers.co.kr 💡 접근 1. 문자열들 파싱해서 시작 시간, 처리 시간을 구한 뒤 리스트에 넣었다. 2. 각 구간의 처리량을 구하는 부분에서 시간을 좀 오래 잡아먹었다. 👩‍💻 코드 import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; p..

[Effective Java]25.톱레벨 클래스는 한 파일에 하나만 담으라

소스 파일하나에 톱레벨 클래스를 여러개 선언할 수 있다. 하지만 이러한 선언은 아무런 득이 없고 심각한 위험을 감수해야 한다. 한 클래스를 여러가지로 정의하게 되는데, 그 중 어느 것을 사용할지는 어느 소스 파일을 먼저 컴파일하냐에 따라 달라진다. 구체적인 예로 확인해보자. 다음 소스 파일은 Main 클래스 하나를 담고 있고, Main 클래스는 다른 톱레벨 클래스 2개(Utensil과 Dessert)를 참조한다. public class Main { public static void main(String[] args) { System.out.println(Utensil.NAME + Dessert.NAME); } } 그리고 Utensil과 Dessert 클래스가 Utensil.java라는 한 파일에 정의되어..

Book/Effective Java 2022.07.06

[Effective Java]24.멤버 클래스는 되도록 static으로 만들라

중첩 클래스란 다른 클래스 안에 정의된 클래스다. 중첩 클래스는 자신을 감싼 바깥 클래스에서만 쓰여야 하며, 그 외에 쓰임새가 있다면 톱레벨 클래스로 만들어야 한다. 중첩 클래스의 종류는 정적 멤버 클래스, (비정적) 멤버 클래스, 익명 클래스, 지역 클래스 4가지가 있다. 이 중 첫번째를 제외한 나머지는 내부 클래스에 해당한다. 이번 아이템에서는 각각의 중첩 클래스를 언제, 왜 사용해야하는지 알아볼 것이다. 먼저 가장 간단한 정적 멤버 클래스이다. 정적 멤버 클래스는 다른 클래스 안에 선언되고 바깥 클래스의 private 멤버에도 접근할 수 있다는 점만 빼면 일반 클래스와 똑같다. 정적 멤버 클래스는 다른 정적 멤버와 똑같은 접근 규칙을 적용받는다. 정적 멤버 클래스는 흔히 바깥 클래스와 함께 쓰일 때..

Book/Effective Java 2022.07.06

[Effective Java]23.태그 달린 클래스보다 클래스 계층구조를 활용하라

두 가지 이상의 의미를 표현할 수 있으며 그중 현재 표현하는 의미를 태그 값으로 알려주는 클래스가 있다. 태그 달린 클래스에는 단점이 많다. 열거 타입 선언, 태그 필드, switch 문 등 쓸데 없는 코드가 많다. 여러 구현이 한 클래스에 혼합돼 있어서 가독성도 나쁘다. 다른 의미를 위한 코드도 언제나 함께 하니 메모리도 많이 사용한다. 그리고 인스턴스의 타입만으로는 현재 나타내는 의미를 알 길이 전혀 없다. 한마디로, 태그 달린 클래스는 장황하고 오류를 내기 쉽고 비효율적이다. 자바와 같은 객체 지향 언어는 타입 하나로 다양한 의미의 객체를 표현하는 훨씬 나은 수단을 제공한다. 바로 클래스 계층구조를 활용하는 서브타이핑이다. 태그 달린 클래스는 클래스 계층구조를 어설프게 흉내낸 아류일 뿐이다. 태그 ..

Book/Effective Java 2022.07.06

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

인터페이스는 자신을 구현한 클래스의 인스턴스를 참조할 수 있는 타입의 역할을 한다. 달리 말해 클래가 어떤 인터페이스를 구현한다는 것은 자신의 인스턴스로 무엇을 할 수 있는지를 클라이언트에게 얘기해주는 것이다. 인터페이스는 오직 이 용도로만 사용해야 한다. 이 지침에 맞지 않는 예로 상수 인터페이스라는 것이 있다. 상수 인터페이스란 메서드 없이 상수를 뜻하는 static final 필드로만 가득 찬 인터페이스이다. 이 상수들을 사용하려는 클래스에서는 정규화된 이름을 쓰는 걸 피하고자 그 인터페이스를 구현하곤 한다. 상수 인터페이스 안티패턴은 인터페이스를 잘못 사용한 예다. 클래스 내부에서 사용하는 상수는 외부 인터페이스가 아니라 내부 구현에 해당한다. 따라서 상수 인터페이스를 구현하는 것은 이 내부 구현..

Book/Effective Java 2022.07.06

[2022 카카오 블라인드]양궁 대회★

📍 문제 설명 https://school.programmers.co.kr/learn/courses/30/lessons/17687 프로그래머스 코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요. programmers.co.kr 💡 접근 x발을 모든 과녁에 맞춰보고 점수를 계산해봐야 한다. 단, 뻗어나가는 과정에서 어피치와 같은 과녁수일 때 까지만 루프를 돌려서 라이언이 +1발만 쐈을 때 점수를 얻을 수 있게 해야 한다. 👩‍💻 코드 import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; impor..

[2018 카카오 블라인드 3차]파일명 정렬

📍 문제 설명 https://school.programmers.co.kr/learn/courses/30/lessons/17686 프로그래머스 코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요. programmers.co.kr 💡 접근 문자열 관련 문제 였다. 1. HEAD, NUMBER, TAIL 부분을 알맞게 파싱한다. 2. 원본 파일명을 그대로 출력해야 하니 File 클래스를 따로 만들어서 원본 데이터를 저장한다. 3. Comparable을 구현해서 주어진 정렬에 맞게 구현한다. 👩‍💻 코드 import java.io.BufferedReader; import java.io.IOException; im..