Object 조상님에서 toString()은 ClassName@hashCodeByHex 를 던져주신다 이 값은 딱히 궁금하지 않았는데.. 그러므로 인스턴스에 대한 야무진 정보를 제공해주려면 toString()도 재정의해줘야 한다 조슈아 형님은 사용하기에 즐겁고 디버깅 하기 쉽기 때문에 반드시 구현하라고 하셨다 그에 앞서 클래스에 대한 야무진 정보가 문자열 형태로 왜 필요한가부터 고민할 필요가 있다 System.out.println()으로 인스턴스를 찍어보는 자바 연습 단계를 지났다면 toString이 도대체 왜 필요한가? 나는 지금껏 프로젝트에서 toString() 메서드를 요긴하게 사용해 본 적이 없어 열심히 찾아봤다 마크씨가 남겨준 답변과 그 아래 달린 코멘트를 유심히 보자 인스턴스에 대한 문맥 제공..
Item11은 equals 재정의할 때 hashCode도 반드시 재정의하라는 내용이다 equals를 직접 작성하고 싶어서 안달이 난 게 아니라면 그냥 롬복이 제공하는 걸로 쓰자 자바는 안 그래도 boiler plate 때문에 코드 길이가 긴 놈인데 코드 흥선대원군 마냥 롬복을 쓰지 않겠다면 프로젝트 코드가 금세 팔만대장경 뺨 칠 수준이 될 것이다 특히 이는 알고리즘 문제 풀 때 C++, python과 비교해보면 코드 길이 차이가 체감이 된다 한 달 전쯤 잠깐 코틀린 인 액션 한 바퀴 돌리면서 코틀린 좀 핥아봤는데 많은 문제가 개선된 것 같다 아직까지는 대규모 프로젝트에 도입하기엔 이른 감이 없지 않은데 네카라쿠배당토가 힘내서 레퍼런스 뿌려주면 좋겠다 이전 장에서 @EqualsAndHashCode 사용할 ..
equals를 재정의 하고 싶다면 일반 규약을 지켜야 한다 일반 규약은 다음과 같다 1. 반사성, reflexibility x가 null이 아닐 때 모든 x에 대하여 x.equals(x)는 true 2. 대칭성, symmetry null이 아닌 두 값 x, y가 있을 때, x.equals(y) == y.equals(x)가 true라면 그 반대도 성립해야 한다 3. 추이성, transitivity null이 아닌 세 값 x, y, z가 있을 때, x.equals(y) == true, y.equals(z) == true면 x.equals(z) == true 4. 일관성, consistency x, y의 값이 변하지 않을 때 x.equals(y) == true라면 언제 호출하더라도 false로 변해선 안 된다..
Item09는 try-finally 보다 try-with-resources를 사용하라 말한다 당연하다, try-finally로 자원 반환을 직접할 필요가 없다 한 때는 try-finally로 자원을 직접 닫고 메서드를 끝내던 시기가 있었다 try-finally로 명시해 자원을 반환하던 이는 지겨운 반복 작업에서 벗어나고자 try-with-resources를 개발했을 것이다 그렇다면 자바를 사용하는 우리와 같은 입장에서는 무조건 쓰는 것이 좋다 다른 API는 트레이드오프라도 있지만 try-with-resources 만큼은 절대적이다 그냥 쓰자 써야할 이유를 굳이 더 붙이자면 try-finally 사용 시에 try 절에서 잘못된 파일을 열어 예외가 발생했는데 finally 절에서 파일을 닫기 위해 file...
Item08의 핵심은 자바에서 제공하는 두 가지 객체 소멸자 finalizer, cleaner를 사용하지 말라는 것이다 핵심을 충실히 따라 앞으로도 모르고 지내도록 하자 여기서 글을 끝마칠 수도 있는 내용이지만 왜인지 한번 알아보자 이제는 당연해져 버렸다 밸덩부터 읽고 시작하자 https://www.baeldung.com/java-finalize finalizer, cleaner라는 메서드가 존재하는 게 아니라 사실 finalize(), clean() 메서드를 의미한다 C++에서는 개발자가 메모리를 직접 다루기 때문에 객체 소멸자도 중요한 의미를 갖지만 자바는 다르다 GC가 우리가 치워야 할 똥을 대신 치워주고 try-finally 문으로 명시적으로 자원을 닫아줄 수 있으며 보다 발전된 try-with-..
자바는 참 편하다 개발자가 신경 쓰지 않아도 메모리 관리를 척척 해주고 write once, run anywhere 정신으로 각각의 운영체제 별로 코드를 따로 작성하지 않아도 된다 JVM 덕분에 편한 인생을 살고 있지만 그럼에도 메모리 관리를 직접 해줘야 하는 경우도 있다 1. 책의 예시에서 나오는 자기 메모리를 직접 관리하는 Stack과 같은 클래스 작성 시 2. 애플리케이션 내의 캐시 이용 시 3. 리스너 / 콜백을 이용하는 이벤트 기반으로 작성 시 대부분의 상황에서는 JVM이 우리의 할 일을 대신하여 메모리라는 방을 청소해준다 JVM이 해주지 못하는 예외의 경우가 위 세가지 상황 같은 것이고 제대로 처리하지 않으면 메모리 누수로 연결된다 다 쓴 참조를 가지고 있는 경우 더 이상 사용할 일이 없어도 ..
자바가 오라클로 인수되면서 저물어 간다는 여론도 많고 자바스크립트의 떡상으로 위상이 많이 떨어지긴 한 것 같다 자바 사용자 입장에서는 가슴 아픈 일이 아닐 수 없다 근데 난 자바의 요즘 행보를 보면 실상은 다르다고 생각한다 벌써 나온지 8년 된 자바 세계의 혁명이었던 자바 8부터 FP를 강력히 지원하기 위해 스트림, 람다가 도입되고 인터페이스에 default 메서드를 넣을 수 있어 하위 호환성을 유지하며 확장해 갈 수 있게 됐다 이후에도 버전업 하면서 코틀린의 data class에 해당하는 record, switch case 문을 간편하게 사용할 수 있는 pattern matching도 나오고 한정적 상속을 가능케 하는 sealed 키워드 등등 자바도 계속해서 발전하고 있다 실무에서는 아무래도 언어 자체..
Item06의 핵심은 쓰잘데기 없는 객체를 생성하지 말라는 것이다 대표적인 예로 정규표현식이 있다 String의 matches 메서드를 이용하면 str 문자열이 정규표현식에 맞는지 비교해 boolean 값을 반환한다 내부 구현이 궁금하다면 String.matches -> Pattern.matches -> Pattern.compile -> Pattern()을 따라가 보자 String.matches 에서 문제가 되는 부분은 new Pattern(regex, 0) 부분이다 쓸데없이 Pattern 객체가 생성된다 정규표현식을 사용해야 하는 데이터가 매우 많은데 매번 String의 matches를 호출하면 어떻게 될까? 프로그램이 터지는 건 아니고 좀 느려진다, 그럼에도 불구하고 다른 방법을 사용해야 한다 더 좋..
Item05는 자원을 때려 박지 말고 외부에서 주입받을 수 있도록 만들라는 것이 주요 내용이다 한 줄로 써놔서 간단해보이지만 객체지향의 핵심이라 할 수 있다 개인이 진행하는 토이 프로젝트가 아니라면 첫 출시와 비교해서 달라지지 않을 프로젝트는 없을 것이다 모두가 만족해할 기능은 없을 것이고 특정 기능에 다수가 만족하더라도 소수는 싫어할 수도 있다 마음 넓은 프로젝트는 구닥다리 IE의 낮은 버전까지도 지원해줘야 하고 그들만을 위한 기능도 추가해줘야 한다 계속해서 변화하고, 기존 코드에 추가되어야 할 코드가 잔뜩 있는데 기존 코드를 바꿀 수 없다면 어떻게 될까? 극단적인 예시지만 때려 박는 코드에선 현실이 된다 하위 호환성까지 알뜰살뜰 챙기는 자바에서 타격이 더욱 크다 공개 API는 쉽게 바꿀 수 없다 더 ..
프로젝트를 진행하다 보면 문자열, 숫자 상수만을 담은 Constant 클래스를 작성할 때가 종종 있다 다양한 클래스에서 사용할 수 있는 Utility 클래스도 마찬가지다 두 클래스의 목적은 특정 클래스에 속하지 않으면서 프로젝트 전체에서 유용하게 사용할 수 있는 코드를 일반화하는 것이다 상수 클래스의 경우 public static final로 한 번만 초기화된 상태로 변경할 수 없도록 해두고 유틸리티 클래스의 경우 public static 으로 접근을 허용하며 메서드를 가진 클래스의 인스턴스화 없이도 사용하게 한다 따라서 두 클래스 모두 인스턴스화될 필요가 없으니 생성자를 private으로 두어 상속 / 인스턴스화를 할 수 없게 해야 한다 사실 상수, 유틸리티 클래스는 인스턴스화 될 필요가 없고 되면 낭..
싱글턴이란 애플리케이션 전체에서 단 하나만 존재하는 인스턴스를 의미한다 그러면 왜 단 하나만 필요할까? 크게 보면 두 가지 이유가 있다 1. 함수형 프로그래밍에서 자주 사용되는 불변 객체로 사용하기 위해 2. 생성 비용이 너무 비싸고, 스레드 간 공유해도 안전한 컴포넌트인 경우 1번은 Java Web Application을 만들 때 흔히들 사용하는 DTO 형태에서 상태 변경만 하지 못하도록 하면 된다 2번은 JPA에서 사용되는 EntityManagerFactory와 같은 객체를 예로 들 수 있다 EntityManagerFactory는 스레드 간 공유해도 안전하며 생성 비용이 크다 싱글턴을 만드는 방식은 어떻게 될까? 1. 생성자를 private으로 만들고 인스턴스 반환은 static method를 이용한..
인스턴스 생성할 때 받아야 하는 매개변수가 무지막지하다면 어떻게 해야 할까? 1. telescoping constructor pattern 2. java beans pattern 3. builder pattern 점층적 생성자 패턴은 받아야 하는 생성자 오버로딩을 통해 매개변수 수를 늘려가는 것이다 매개변수 개수에 따라 계속 늘어나야 하므로 유지보수까지 생각한다면 지옥이나 다름없다 boiler plate가 차지하는 코드가 도메인에서 필요한 필드, 메서드 보다 더 많아질 수 있다 Java Beans Pattern 은 기본 생성자를 하나 두고 setter로 필드 값을 지정해준다 하나의 instance 만들려면 setter 난무해야 하고 필수 값을 빠뜨리고 생성할 수도 있기 때문에 일관성이 보장되지 않는다 s..
최근 이펙티브 자바 3판 1 회독을 끝냈다 다른 사람들의 리뷰, 후기를 보면 책 수준이 굉장하다는데 나도 동감한다 개인적으로 책을 볼 때 1회독은 빠르게 흐름을 잡고 2-3 회독하면서 깊게 이해하는 편이라 야무진 책 내용을 기억에 오래 붙잡아두기 위해 정리해보고자 한다 책 내용을 훑는데 그치지 않고 한 발자국 더 나아가 개인적인 의문점에 대해 찾아보고 정리해야겠다 아이템 1의 핵심 내용은 new 연산자를 사용해 클래스를 생성하는 코드 대신 static factory method를 사용하라는 것이다 왜 그래야 할까? 장점은 다음과 같다 1. new Class() 대신 이름을 가진 메서드로 호출할 수 있다 2. 호출될 때마다 인스턴스를 생성할 필요가 없다 3. 반환 타입의 하위 타입 객체를 반환할 수 있다 ..
객체지향의 역사, 특징 절차적인 언어의 대안으로써 객체지향 개념이 탄생, 코드 간의 관계를 맺어 유기적인 프로그래밍이 가능하게 되었음 코드의 재사용성 향상, 유지보수 용이, 중복 제거 세 가지 핵심 기능 객체를 지향하는 프로그래밍 방식 객체 하나하나가 각자의 책임을 가지고 있고 그 책임에 맞는 기능을 수행해 서로 협력을 이룬다. 협력을 통해 Application 을 구성한다. 이 때 서로에게 요청하는 방식이 message를 전송하는 것 OOP의 설계원칙 Single Responsibility Principle 객체는 단 하나의 책임만 가지고 있어야 한다. 하나의 기능만 수행하는 걸 의미하는 것은 아니며 [오브젝트] 에서는 변경의 이유가 하나여야 한다고 한다. Open Close Principle 변경에는..