추상 클래스와 인터페이스의 공통점과 차이점에 대해서는 넘어가고 바로 본론으로 들어가도록 하자. 우선 JAVA 8 부터 인터페이스에서 Default Method 를 제공하기 때문에 추상 클래스와 같이 인스턴스 메서드를 구현한 형태로 제공할 수 있다. 기존에 "인터페이스에는 추상 메서드로만 구성되어야 한다" 에서 벗어나 완성된 메서드를 제공할 수 있다는 것이다. 둘의 가장 큰 차이는 추상 클래스가 정의한 타입을 구현하는 클래스는 반드시 추상 클래스의 하위 클래스가 되어야 한다는 점이다. 즉, 반드시 상속을 통해서만 추상 클래스 사용할 수 있다. 이 자체만으로 자바의 다중상속으로 인해 큰 제약이 생기게 된다. 이외에도 인터페이스는 믹스인 정의에 안성맞춤이고, 기존 클래스에도 손쉽게 구현할 수 있는 등 다양한 ..
알다시피 상속은 코드 재사용을 구현하기 위한 강력한 방법이다. 하지만 잘못 사용할 경우 오류를 내기 쉬운 프로그램을 만들게 된다. 이러한 문제는 상위 클래스와 하위 클래스를 동일한 개발자가 개발하지 않은 경우에 발생하게 된다. 따라서 다른 클라이언트가 내가 만든 클래스를 상속받을 수 있게 하려면 주의해야 한다. 상속은 코드 재사용성을 높여주지만 캡슐화를 깨뜨리게 된다. 상위 클래스가 어떻게 구현되느냐에 따라 하위 클래스의 동작에 이상이 생길 수 있다는 말이다. (상위 클래스가 변경되는 등의 변화로 인해서!!) 따라서 상위 클래스 개발자가 상속을 고려한 문서화를 하거나 상속하려는 클라이언트가 상위 클래스의 변화에 맞춰 하위 클래스를 수정해줘야 한다. public class InstrumentedHashSe..
불변 클래스란 간단히 말해 그 인스턴스의 내부 값을 수정할 수 없는 클래스를 말한다. 불변 클래스로 생성된 인스턴스는 생성자로 인해 객체가 생성된 이후부터 객체가 가비지 컬렉터에 의해서 해제될 때까지 절대 변하지 않는다. 우리는 이미 다양한 불변 클래스를 사용하고 있고 그 대표적인 예로 String, BigInteger, Boolean 등이 존재한다. 불변 클래스의 가장 큰 장점은 설계하고 구현하기 쉬우며 오류가 생길 여지가 적고 훨씬 안전하다는 점이다. 그러면 불변 클래스를 만들기 위한 규칙에 대해서 살펴보자. 객체의 상태를 변경하는 메서드(Ex. Setter 메서드)를 제공하지 않는다. 클래스를 확장할 수 없도록 한다. 즉 해당 클래스를 상속받을 수 없도록 만들어야 한다. 모든 인스턴스 필드를 fin..
어설프게 설계된 컴포넌트와 잘 설계된 컴포넌트의 가장 큰 차이는 클래스 내부 데이터와 내부 구현 정보를 외부 컴포넌트로부터 얼마나 잘 숨겼느냐다. 잘 설계된 컴포넌트는 모든 내부 구현을 완벽하게 숨겨, 구현과 API 를 깔끔하게 분리한다. 이러한 개념은 OOP 의 원칙 중 하나인 캡슐화, 정보 은닉을 지키기 위한 것이다. 그러면 이러한 정보 은닉을 구현함으로써 얻을 수 있는 장점들에 대해서 살펴보자. 시스템 개발 속도를 높인다. 여러 컴포넌트를 병렬로 개발할 수 있기 때문이다. 시스템 관리 비용을 낮춘다. 각 컴포넌트를 빨리 파악해서 디버깅할 수 있고, 다른 컴포넌트로 교체하는 부담도 적기 때문이다. 정보 은닉 자체가 성능을 높여주지는 않지만, 성능 최적화에 도움을 준다. 소프트웨어 재사용성을 높인다. ..
Object 클래스는 객체를 만들 수 있는 구체 클래스면서 중요한 특징으로 모든 클래스의 부모 클래스라는 점이 있다는 것을 기억해야 한다. Object 클래스에는 equals, hashCode, toString, clone 등 몇 가지 메서드가 포함되어 있는데 이러한 메서드들은 모두 재정의를 염두에 두고 제작된 메서드이다. 따라서 이러한 메서드들을 재정의할 때 지켜야 하는 일반 규약들이 명확하게 정의되어 있다. 이러한 일반규약은 당연히 지켜진다고 가정되기 때문에 지키지 않았을 때 HashSet, HashMap과 같은 것에서 오동작을 발생시킬 수 있다. 이번 포스팅에서는 Object 클래스에 포함되어 있는 equals, hashCode, toString, clone 을 재정의할 때 지켜야할 일반규약에 대해..
자바 라이브러리에는 직접 close 메서드를 통해 닫아줘야 하는 것들이 많다. 가장 쉽게 접할 수 있는 Scanner 클래스부터 객체를 사용한 후 close 메서드를 통해 닫아줘야 한다. 이외에도 InputStream, OutputStream, java.sql.Connection 등 다양한 것들이 존재한다. 자원을 사용한 후 close 메서드 호출을 통해 닫아주는 것을 가볍게 생각하면 안된다. 왜냐하면 예측할 수 없는 성능 문제로 이어질 수 있기 때문이다. try-finally 전통적으로 자원을 사용한 후 닫기 위한 방법으로 아래 예제코드와 같은 try-finally를 많이 사용했습니다. static String firstLineOfFile(String path) throws IOException { B..