java
-
25. 톱레벨 클래스는 한 파일에 하나만 담으라JAVA/Effective java 2021. 3. 9. 14:28
소스 파일 하나에 톱레벨 클래스를 여러 개 선언하더라도 자바 컴파일러는 불평하지 않는다. 하지만 아무런 득이 없을 뿐더러 심각한 위험을 감수해야 하는 행위다. 이렇게 하면 한 클래스를 여러 가지로 정의할 수 있으며, 그 중 어느 것을 사용할지는 어느 소스 파일을 먼저 컴파일하느냐에 따라 달라지기 때문이다. 다음 소스 파일은 Main 클래스 하나를 담고 있고, Main 클래스는 다른 톱레벨 클래스 2개(Utensil과 Dessert)를 참조한다. Utensil과 Dessert 클래스가 Utensil.java 라는 한 파일에 정의되어 있다고 해보자. 물론 Main을 실행하면 pancake를 출력한다. 이제 우연히 똑같은 클래스를 담은 Dessert.java라는 파일을 만들었다고 해보자. 운 좋게 javac ..
-
24. 멤버 클래스는 되도록 static으로 만들라JAVA/Effective java 2021. 3. 8. 14:19
중첩 클래스란 다른 클래스 안에 정의된 클래스를 말한다. 중첩 클래스의 종류는 정적 멤버 클래스, (비정적) 멤버 클래스, 익명 클래스, 지역 클래스, 이렇게 네 가지다. 이번 아이템에서는 각각의 중첩 클래스를 언제 그리고 왜 사용해야 하는지 이야기한다. 정적 멤버 클래스와 비정적 멤버 클래스 정적 멤버 클래스는 다른 클래스 안에 선언되고, 바깥 클래스의 private 멤버에도 접근할 수 있다는 점만 제외하고는 일반 클래스와 똑같다. 정적 멤버 클래스는 흔히 바깥 클래스와 함께 쓰일 때만 유용한 public 도우미 클래스로 쓰인다. 계산기가 지원하는 연산 종류를 정의하는 열거 타입을 예로 생각해보자. Operation 열거 타입은 Calculator 클래스의 public 정적 멤버 클래스가 되어야 한다...
-
23. 태그 달린 클래스보다는 클래스 계층구조를 활용하라JAVA/Effective java 2021. 3. 7. 14:23
두 가지 이상의 의미를 표현할 수 있으며, 그 중 현재 표현하는 의미를 태그 값으로 알려주는 클래스를 본 적이 있을 것이다. 다음 코드는 원과 사각형을 표현할 수 있는 클래스다. 문제점 열거 타입 선언, 태그 필드, switch 문 등 쓸데없는 코드가 많다. 여러 구현이 한 클래스에 혼합돼 있어서 가독성도 나쁘다. 다른 의미를 위한 코드도 언제나 함께 해서 메모리도 많이 사용하며 또 다른 의미를 추가하려면 코드를 수정해야 한다. 예를 들어 새로운 의미를 추가할 때마다 모든 switch 문을 찾아 새 의미를 처리하는 코드를 추가해야 하며, 하나라도 빠뜨리면 런타임에 문제가 불거져 나올 것이다. 마지막으로 인스턴스 타입만으로는 현재 나타내는 의미를 알 길이 전혀 없으며 한마디로, 태그 달린 클래스는 장황하고..
-
22. 인터페이스는 타입을 정의하는 용도로만 사용하라JAVA/Effective java 2021. 3. 6. 19:34
인터페이스는 자신을 구현한 클래스의 인스턴스를 참조할 수 있는 타입 역할을 한다. 즉, 클래스가 어떤 인터페이스를 구현한다는 것은 자신의 인스턴스로 무엇을 할 수 있는지를 클라이언트에게 이야기하는 것이며 인터페이스는 오직 이 용도로만 사용해야 한다. 이 지침에 맞지 않는 예로 소위 상수 인터페이스라는 것이 있다. 상수를 뜻하는 static final 필드로만 가득 찬 인터페이스가 이를 말한다. 이 상수들을 사용하려는 클래스에서는 정규화된 이름을 쓰는 걸 피하고자 그 인터페이스를 구현하곤 한다. 상수 인터페이스 안티패턴은 인터페이스를 잘못 사용한 예다. 클래스 내부에서 사용하는 상수는 외부 인터페이스가 아니라 내부 구현에 해당한다. 따라서 상수 인터페이스를 구현하는 것은 이 내부 구현을 클래스의 API로 ..
-
변경 가능성을 최소화하라JAVA/Effective java 2021. 2. 11. 13:10
불변 클래스란 간단히 말해 그 인스턴스의 내부 값을 수정할 수 없는 클래스다. 불변 인스턴스에 간직된 정보는 고정되어 객체가 파괴되는 순간까지 절대 달라지지 않는다. 자바 플랫폼 라이브러리에도 다양한 불변 클래스가 있고 String, 기본 타입의 박싱된 클래스들, BigInteger, BigDecial이 있다. 불변으로 설계하는 이유는 그럴만한 이유가 있다. 불변 클래스는 가변 클래스보다 설계하고 구현하고 사용하기 쉬우며, 오류가 생길 여지도 적어 훨씬 안전한다. 클래스를 불변으로 만들려면 다음 5가지 규칙을 따르자. 1. 객체의 상태를 변경하는 메서드(변경자)를 제공하지 않는다. 2. 클래스를 확장할 수 없도록 한다. 이는 하위 클래스에서 객체의 상태를 변하게 하는 것을 막는다. 3. 모든 필드를 fi..
-
클래스와 멤버의 접근 권한을 최소화하라JAVA/Effective java 2021. 1. 23. 01:41
어설프게 설계된 컴포넌트와 잘 설계된 컴포넌트의 가장 큰 차이는 클래스 내부 데이터와 내부 구현 정보를 외부 컴포넌트로부터 얼마나 잘 숨겼느냐다. 잘 설계된 컴포넌트는 모든 내부 구현을 완벽히 숨겨, 구현과 API를 깔끔히 분리한다. 오직 API를 통해서만 다른 컴포넌트와 소통하며 서로의 내부 동작 방식에는 전혀 개의치 않는다. 정보 은닉, 캡슐화라고 하는 이 개념은 소프트웨어 설계의 근간이 되는 원리다. 정보 은닉의 장점 시스템 개발 속도를 높인다. 여러 컴포넌트를 병렬로 개발할 수 있기 때문이다. 시스템 관리 비용을 낮춘다. 각 컴포넌트를 더 빨리 파악하여 디버깅할 수 있고, 다른 컴포넌트로 교체하는 부담도 적다. 정보 은닉 자체가 성능을 높여주지는 않지만 성능 최적화에 도움을 준다. 다른 컴포넌트에..
-
Comparable을 구현할지 고려하라JAVA/Effective java 2021. 1. 21. 17:54
Comparable 인터페이스의 유일무이한 메서드인 compareTo를 알아보자. compareTo는 Object의 메서드가 아니다. compareTo는 Object의 equals와 비슷하지만 두 가지가 다르다. 단순 동치성 비교에 더해 순서까지 비교할 수 있으며 제네릭하다. Arrays.sort(a); Comparable을 구현했다는 것은 그 클래스의 인스턴스들에는 자연적인 순서가 있음을 뜻하고 따라서 Comparable을 구현한 객체들의 배열은 다음처럼 손쉽게 정렬할 수 있는 것이다. 검색, 극단값 계산, 자동 정렬 컬렉션 관리 역시 쉽게 할 수 있다. 다음 프로그램은 명령줄 인수들을 알파벳순으로 출력한다. String이 Comparable을 구현한 덕이다. 사실상 자바 플랫폼 라이브러리의 모든 값 ..
-
clone 재정의는 주의해서 진행하라JAVA/Effective java 2021. 1. 20. 18:09
Cloneable은 복제해도 되는 클래스임을 명시하는 용도의 믹스인 인터페이스지만, 아쉽게도 의도한 목적을 제대로 이루지 못했다. 가장 큰 문제는 clone 메서드가 선언된 곳이 Cloneable이 아닌 Object이고 그마저도 protected라는 데 있다. 따라서 Cloneable을 구현하는 것만으로는 외부 객체에서 clone 메서드를 호출할 수 없다. 그렇다면 메서드 하나 없는 Cloneable 인터페이스는 무슨 일을 할까? 이 인터페이스는 Object의 protected 메서드인 clone의 동작 방식을 결정한다. Cloneable을 구현한 클래스의 인스턴스에서 clone을 호출하면 그 객체의 필드들을 하나하나 복사한 객체를 반환하며, 그렇지 않은 클래스의 인스턴스에서 호출하면 CloneNotSu..