본문 바로가기

Language/Java Plus

(26)
Effective JAVA - Item25 : 톱 클래스 파일은 한 파일에 하나만 담아라 주제 : 톱클래스는 한 소스파일 안에 하나만 담아라. 아래 예시를 살펴보자 // Utensil.java class Utensil { static final String name = "pan"; } class Dessert{ static final String name = "cake"; } // Dessert.java class Utensil { static final String name = "pot"; } class Dessert{ static final String name = "pie"; } // Main.java public static void main(String[] args){ System.out.println(Utensil.name, Dessert.name); } 위와 같이 같은 내용이 있..
Effective JAVA - Item24 : 멤버 클래스는 되도록 static으로 만들어라 주제는 멤버 클래스는 되도록 static으로 만들어다 이고 자세히 살펴보자 우선, 멤버 클래스는 보통 중첩 클래스를 의미한다. 중첩 클래스란 클래스 내부에 정의된 클래스로 enum 클래스가 될 수도 있고 익명클래스가 될 수도 있다. 또한, 중첩 클래스는 자신을 감싼 클래스 안에서만 사용되어야 하고 그렇지 않다면 톱 클래스로써 사용되어야 한다. 중첩 클래스의 종류 정적 멤버 클래스 비정적 멤버 클래스 익명 클래스 지역 클래스 - 정적 멤버 클래스를 제외한 나머지 클래스는 inner class를 의미한다. 각각의 중첩 클래스를 언제 그리고 왜 사용하는지 알아보자 1. public static 멤버 클래스 특징 - 바깥 클래스의 private 멤버 접근 가능 - 바깥 클래스와 함께 쓰일때만 용이한 public..
Effective JAVA - Item23 : 태그 달린 클래스보다는 클래스 계층 구조를 활용하라 태그 달린 클래스 - 아래처럼 태그 필드가 있는 코드를 태그 달린 클래스라고 한다. - 두가지 이상의 의미를 표현할 수 있으며, 그 중 현재 표현하는 의미를 태그값으로 알려주는 클래스 public class Figure { enum Shape {RECTANGLE, CIRCLE}; // 태그 필드 - 현재의 모양을 나타냄 final Shape shape; // Rectangle 일 때만 사용된다. double length; double width; // Circle 일때만 사용 double radius; // 원 생성자 Figure(double radius){ shape = Shape.RECTANGLE; this.radius = radius; } // 사각형 생성자 Figure(double length, ..
Effective JAVA - Item22 : 인터페이스는 타입을 정의하는 용도로만 사용하라 주제 인터페이스는 타입을 정의하는 용도로만 사용해야하고 상수 공개용 수단으로 사용하지 말자. 인터페이스의 주된 역할은 해당 인터페이스를 구현한 클래스를 사용자들이 사용시 그 클래스의 용도를 알려주는 역할을 한다. 하지만, 이 역할만을 수행해야하며, 상수 인터페이스 안티패턴과 같이 static final로만 가득찬 인터페이스를 제공하여 해당 수를 사용하는 방식으로 인터페이스를 구현해서는 안된다. 예를 통해 문제점을 보여주고자한다. 아래의 코드에서 보면 Number 인터페이스를 Test 클래스가 구현했다. public interface Number { static final int one = 1; } public class Test implements Number{ } 기본적으로 클래스 내부에서 사용하는 상..
Effective JAVA - Item21 : 인터페이스는 구현하는 쪽을 생각해서 설계하라. 이 파트는 인터페이스 디폴트 메서드에 대해서 주로 다루고 있다. 내용을 요약하자면 디폴트 메서드를 통해 인터페이스에 새로운 메서드를 추가하는 일이 가능해졌지만 문제가 많으니 항상 인터페이스를 구현할때는 신중하게 할 것을 강조한다. 인터페이스의 가장 큰 단점 자바는 기본적으로 릴리스가 존재한다. 릴리스를 개시하면 사용자들은 그 릴리스를 사용하게 된다. 인터페이스는 자바 8 이전까지 메서드 추가/삭제가 어려웠다. 디폴트 메서드가 부재하던 시절에 새로운 메서드를 추가하거나 삭제한다면 이 인터페이스를 구현한 모든 클래스가 해당 메서드를 삭제 또는 재정의해야했기 때문이다. 하지만 디폴트 메서드가 추가되면서 구현체들은 해당 메서드를 재정의해야함이 강제되지 않기때문에 이런 문제가 줄어드나 싶었다. 그렇지는 않은듯 싶..
Effective JAVA - Item20 : 추상 클래스보단 인터페이스를 우선시하라. 기본적으로 인터페이스와 추상 클래스의 장단점에 대해서 짚고 넘어가보고자 한다. 장단점은 아래와 같다. 추상 클래스 vs 인터페이스 인터페이스 장점 1. 다중 상속 지원 : 여러 인터페이스를 구현할 수 있으므로 다중 상속을 지원한다. 2. 유연한 설계 : 인터페이스는 클래스와 상관없이 다른 클래스가 동일한 인터페이스를 구현하므로 클래스간 교체가 유연하다. 3. 표준화 : 인터페이스를 사용하여 다른 클래스 간에 표준 메서드 시그니처를 정의할 수 있으므로 코드의 일관성과 유지보수성을 높인다. 4. 믹스인에 안성 맞춤 : 믹스인은 해당 클래스가 특정 행위를 한다고 알려주는 방법으로 예시로는 Comparable이 있다. 단점 1. 구현 코드 부재 : 인터페이스는 메서드 시그니처만을 정의하고, 구체적인 구현 코드는..
Effective JAVA - Item19 : 상속을 고려해 설계하고 문서화하라. 그러지 않았다면 상속을 금지하라. 결론 상속을 해서 확장을 했을 때 많은 문제를 일으킨다. 해결 방법은 클래스 상속시 상속을 위해 설계하고 설명해주는 문서를 만드는 것이다. 그렇게 만든 클래스가 아니라면 해당 클래스의 상속을 금지시켜라 상속이 위험한 이유 내가 어떤 클래스를 상속해서 클래스를 만든다고 가정하자. 하지만, 그 상위 클래스는 내가 수정할 수 있는 나의 코드가 아닌 다른 패키지의 클래스를 사용한다면 내가 통제를 할 수가 없다. 따라서, 다음 릴리즈 등에서 변경시 내가 할 수 있는 것이 없다. 따라서 코드 수정, 안정성 면에서 다소 위험하다. 상속을 할 수 있게 하는 방법 : 상속을 위한 설계와 API 문서 작성 1. 메서드를 재정의하면 메서드 내부가 어떻게 동작하는지 상세히 정리하여 문서로 남겨야 한다. -> 어떤 순서로 호출..
Effective JAVA - Item18 : 상속보다는 컴포지션을 사용하라. 주제 "다른 패키지의 구체 클래스를 상속하는 것은 위험 하다." 문제점 // 문제점 : 메서드 호출과 달리 상속은 캡슐화를 깨뜨린다. // = 상위 클래스가 어떻게 구현되는냐에 따라 하위 클래스의 동작에 이상이 생길 수 있다. // = 상위 클래스는 릴리스마다 내부 구현이 변경될 수 있고 이에 따라 하위 클래스가 동작하지 않을 수 있다. // 상위 클래스의 메서드를 재정의하는 것은 내부 모든 동작을 파악하기도 어렵고 문서에 적혀있지 않은 경우도 존재한다 // 또한, 새로운 릴리스에서 내부 변경시 이에 맞추어 모두 수정해야 하기에 유연하지 못한다. 해결 // 해결책 : 컴포지션 // 방법 // 1. 기존의 클래스를 확장하는 대신, 새로운 클래스를 만들고 private 필드로 기존 클래스의 인스턴스를 참조하..