[Effective Java] Item 25. 톱레벨 클래스는 한 파일에 하나만 담으라 1. 톱레벨 클래스 Example.java class Utensil { static final String NAME = "pan"; } class Dessert { static final String NAME = "cake"; } 소스 파일에 하나에 톱레벨 클래스가 여러 개 정의되어 있더라도 컴파일은 가능하다. 그러나 소스 파일의 톱레벨 클래스와 이름이 중복되는 클래스가 외부에 존재하는 경우, 소스 파일의 순서에 따라 컴파일 결과가 달라질 수 있다. Test.java public class Test { public static void main(String[] args) { System.out.println(Utensil.NAME + Dessert.NAME); } private static class U.. Prodo 독서 리뷰 4년 전
[Effective Java] Item 24. 멤버 클래스는 되도록 static으로 만들라 1. 중첩 클래스 중첩 클래스란 다른 클래스 내부에서 정의된 클래스이다. 중첩 클래스는 자신을 감싼 외부 클래스에서만 사용되어야 하며, 그 외의 경우 탑 레벨 클래스로 정의되어야 한다. 정적 멤버 클래스. 비정적 멤버 클래스. 익명 클래스. 지역 클래스. 첫 번째를 제외한 클래스를 모두 Inner Class라고 지칭한다. 2. 멤버 클래스 2.1. 정적 멤버 클래스 정적 멤버 클래스는 외부 클래스의 private 멤버에도 접근할 수 있다. 다른 멤버 필드와 동일한 접근 규칙을 적용받는다. private이면 Outer Class만 사용이 가능하다. 주로 Outer Class와 함께 사용되면 유용한 public 도우미 클래스로 사용된다. 개념상 중첩 클래스의 인스턴스가 바깥 인스턴스와와 독립적으로 존재할 수.. Prodo 독서 리뷰 4년 전
[Effective Java] Item 23. 태그 달린 클래스보다는 클래스 계층구조를 활용하라 1. 태그 달린 클래스 Figure.java class Figure { enum Shape { RECTANGLE, CIRCLE }; // 태그 필드 - 현재 모양을 나타낸다. final Shape shape; // 다음 필드들은 모양이 사각형(RECTANGLE)일 때만 쓰인다. double length; double width; // 다음 필드는 모양이 원(CIRCLE)일 때만 쓰인다. double radius; // 원용 생성자 Figure(double radius) { shape = Shape.CIRCLE; this.radius = radius; } // 사각형용 생성자 Figure(double length, double width) { shape = Shape.RECTANGLE; this.lengt.. Prodo 독서 리뷰 4년 전
[Effective Java] Item 22. 인터페이스는 타입을 정의하는 용도로만 사용하라 1. 인터페이스의 용도 인터페이스란 자신을 구현한 클래스의 인스턴스를 참조할 수 있는 타입 역할이다. 클래스가 어떤 인터페이스를 구현하는 것은 자신의 인스턴스로 무엇을 할 수 있는지를 클라이언트에게 얘기해주는 것이다 2. 안티 패턴 : 상수 인터페이스 PhysicalConstants.java public interface PhysicalConstants { static final double AVOGADROS_NUMBER = 6.022_140_857e23; static final double BOLTZMANN_CONSTANT = 1.380_648_52e-23; static final double ELECTRON_MASS = 9.109_383_56e-31; } 일부 클래스들은 외부 인터페이스에 상수를 선언.. Prodo 독서 리뷰 4년 전
[Effective Java] Item 21. 인터페이스는 구현하는 쪽을 생각해 설계하라 1. 디폴트 메서드 Java 8 부터는 기존의 구현체를 깨뜨리지 않고 인터페이스에 디폴트 메서드를 추가할 수 있다. 그러나 생각할 수 있는 모든 상황에서 불변식을 해치지 않는 디폴트 메서드를 작성하기 어렵다. 1.1. SynchronizedCollection 예시 아파치의 SynchronizedCollection은 메서드를 락 객체로 동기화한 후 내부 컬랙션 객체에게 기능을 위임하는 래퍼 클래스이다. removeIf()를 재정의하고 있지 않다. 만약 Java 8의 동기화 되지 않은 removeIf() 디폴트 구현을 물려받는다면? removeIf()의 구현은 동기화를 모르기 때문에 락 객체를 사용할 수 없다. 멀티 쓰레드 상황에서 호출하면 에러가 발생할 수 있다. Java 플랫폼 라이브러리들은 구현한 인터.. Prodo 독서 리뷰 4년 전
[Effective Java] Item 20. 추상 클래스보다는 인터페이스를 우선하라 1. 다중 구현 메커니즘 Java가 제공하는 다중 구현 메커니즘은 추상 클래스와 인터페이스가 있다. 두 메커니즘 모두 인스턴스 메서드를 구현 형태로 제공할 수 있다. 1.1. 추상 클래스 추상 클래스가 정의한 타입을 구현하는 클래스는 반드시 추상 클래스의하위 클래스가 되어야 하는 제약이 있다. 추상 클래스를 확장한 클래스는 다른 클래스를 상속받을 수 없게 된다. 기존 클래스 위에 새로운 추상 클래스를 끼워넣기 어렵다. 두 클래스가 같은 추상 클래스를 확장하고자 하는 경우? 해당 추상 클래스는 두 클래스의 공통 조상이어야 한다. 그렇지 않으면 계층 구조에 혼란을 일으킨다. 1.2. 인터페이스 인터페이스가 선언한 메서드를 모두 정의한 클래스는 상속 여부와 상관없이 같은 타입이 된다. 기존 클래스들도 새로운 .. Prodo 독서 리뷰 4년 전
[Effective Java] Item 19. 상속을 고려해 설계하고 문서화하라. 그러지 않았다면 상속을 금지하라 1. 상속의 문서화 상속을 염두하지 않고 설계했으며 상속의 주의점을 문서화하지 않은 외부(개발자에게 통제권이 없는) 클래스를 상속하는 것은 위험하다. 상속용 클래스는 오버라이드 할 수 있는 메서드들을 내부적으로 어떻게 이용하는지(자기사용) 문서로 남겨야 한다. 오버라이드할 수 있는 메서드란 final이 아닌 public 혹은 protected 메서드이다. 재정의 가능 메서드를 호출할 수 있는 모든 상황을 명시해야 한다. API 문서의Implementation Requirements로 시작하는 절이 해당 상황을 명시한다. XX 메서드를 재정의하면 YY 메서드를 사용하는데 영향을 끼칠 수 있다 등의 내용이다. 단순히 내부 매커니즘을 문서화하는 것이 아니라, 효율적인 하위 클래스 제작을 위해 클래스의 내부 동.. Prodo 독서 리뷰 4년 전
[Effective Java] Item 18. 상속보다는 컴포지션을 사용하라 1. 상속 상속은 코드를 재활용하는 강력한 방법이다. 다음의 경우 상속을 활용해도 안전하다. 상위 클래스와 하위 클래스 모두 같은 개발자가 통제하는 패키지에 속해 있다. 클래스가 확장할 목적으로 설계되었으며 문서화가 잘 되어있다. 그러나 일반적인 구체 클래스를 패키지 경계를 넘어, 다른 패키지의 구체 클래스를 상속하는 것은 위험하다. (인터페이스 상속은 논외로 친다.) 상위 클래스가 어떻게 구현되느냐에 따라 하위 클래스의 동작에 이상이 생길 수 있다. 상위 클래스는 릴리스마다 내부 구현이 달라질 수 있다. 여파로 코드 한 줄 변경하지 않은 하위 클래스가 오작동할 수 있다. 상위 클래스 변화의 영향이 하위 클래스에게 끼친다. 2. 상속의 단점 MyHashSet.java public class MyHashS.. Prodo 독서 리뷰 4년 전