Programming/Java 24

[Effective Java] item14 - Comparable을 구현할지 고려하라.

Comparable을 구현할지 고려하라! 의도하던 아니던, 값을 비교해야 하는 경우는 많다. 가령 정렬을 한다거나, 이분 탐색을 한다거나, TreeMap/Set을 쓴다면... 따라서 새로운 객체를 만들게 된다면 Comparable을 구현할지 고려해야 한다. Comparable은 어떻게 생겼을까? public interface Comparable { public int compareTo(T o); } 결국 Comparable을 구현한다는 것은 compareTo를 정의하는 것과 마찬가지 일 것이다. equals를 열심히 공부했다면, compareTo의 규약도 쉽게 읽힐 것이다. 이 객체의 주어진 객체의 순서를 비교하는데, 이 객체가 주어진 객체보다 작으면 음의 정수를, 같으면 0을, 크면 양의 정수를 반환한..

Programming/Java 2021.02.18

[Effective Java] item13 - clone 재정의는 주의해서 진행하라.

clone 재정의는 주의해서 진행하라! clone은 원본 객체의 필드값과 동일한 값을 가지는 새로운 객체를 생성하는 메소드이다. protected native Object clone() throws CloneNotSupportedException; 앗! native다. 또한 CloneNotSupportedException을 던지는데, 이는 clone을 사용할 수 없는 객체에서 clone을 사용하려고 할 때 발생하는 예외일 것이다. 그렇다면 clone을 쓸 수 있을지, 없을지 어떻게 판단할 수 있을까? 바로 Cloneable을 구현했는지 확인하면 된다. 그렇다면 Cloneable은 어떻게 생겼을까? public interface Cloneable {} 텅텅 비었다? 대체 이게 무슨 역할을 할까? 구현되어 ..

Programming/Java 2021.02.17

[Effective Java] item12 - toString을 항상 재정의하라.

toString을 항상 재정의하라!Object의 toString의 결과물은 다음과 같다.Chicken@12a58z단순히 클래스 이름@16진수로 표기한 해시코드 형식인데, 우리가 객체를 print 할 때 저런 결과물을 바라고 출력하는게 아니지 않을까?규약에 따르면 toString은 간결하면서 사람이 읽기 쉬운 형태의 유익한 정보를 반환해야 한다.사실 일반적으론 toString은 그 객체가 가진 모든 주요 정보를 반환하는게 최고다. 최소한 디버깅용으론 좋지 않을까? 문제는 객체의 사이즈가 크다면 담기 힘들 것이다.대한민국 치킨집이 20000개가 넘는데, 해당 자료를 담은 객체가 있다고 가정하자. 모든 데이터를 출력하도록 toString을 재정의하면 대참사가 날 것은 뻔하다! toString을 재정의 할 때는..

Programming/Java 2021.02.12

[Effective Java] item11 - equals를 재정의하려거든 hashCode도 재정의하라.

equals를 재정의하려거든 hashCode도 재정의하라! 앞에서 equals를 재정의했다. 이제 대부분의 Collection에서 내가 새로 만든 클래스를 잘 사용할 수 있다. 문제는 '대부분'이라는 것이다. 전부가 아니라! HashMap을 떠올려 보자. 이 친구는 값을 어떻게 삽입하고, 삭제하고, 탐색할까? 바로 해시다. 그런데 우리는 equals만 재정의 했기 때문에 equals로 같은 인스턴스라 할 지라도 hashCode 상에선 다른 인스턴스로 취급 될 수 있다! (사실 Object에서 정의된 hashCode를 보면 물리적으로 다른 객체는 모두 hashCode도 다르다.) 기본적인 규약 Object 명세의 규약을 잠시 살펴보자. equals 비교에 사용되는 정보가 변경되지 않았다면, 애플리케이션이 ..

Programming/Java 2021.02.12

[Effective Java] item10 - equals는 일반 규약을 지켜 재정의하라.

equals는 일반 규약을 지켜 재정의하라! 다른 언어를 쓰다가 Java로 넘어가게 되면 가장 많이 헷갈려하는 것이 String을 비교할 때다. String str1 = "Hello"; String str2 = "Hello"; System.out.println(str1 == str2); 보통 저렇게 쓰고 "어?? 왜 안되는 걸까???" 이러고 앉아 있다. 당연히 이 글을 읽을 수준이 된다면 왜 안되는지 너무나도 쉽게 알 것이다. equals 가 그 답이다. 일반적으로 객체를 생성할 때는 Object에서 final로 정의하지 않는 것들을 오버라이딩 해서 사용하는게 일반적이다. (equals, hashCode, toString, clone, finalize) 그런데 대부분 equals을 오버라이딩 할 때 I..

Programming/Java 2021.02.10

[Effective Java] item9 - try-finally 보다는 try-with-resource를 사용하라.

try-finally 보다는 try-with-resource를 사용하라! 백준을 자바로 풀면 bufferedReader를 참 많이 사용할 것이다. 사실 단순히 문제를 푸는거라 close를 안하고 제출하는 소스가 많긴 한데, 어쨌든 close를 통해 직접 닫아줘야 한다. 위에서 말했던 것 처럼 수많은 코드가 저걸 그냥 안 닫고 넘겨버리는 경우가 있는데, 이런 경우엔 예측 불가능한 성능 문제로 이어지곤 한다. 앞에서 finalizer를 설명하면서 안전 장치로 사용할 수 있다곤 말했는데, 이 친구는 썩 좋은 친구는 아니라서... static String doReader(String path) throws IOException { BufferedReader br = new BufferedReader(new Fi..

Programming/Java 2021.02.06

[Effective Java] item8 - finalizer와 cleaner 사용을 피하라.

finalizer와 cleaner 사용을 피하라! 공부하면서 느낀거지만, 내용이 꽤나 어렵다. 같이 스터디 하는 현업자분들도 실제로 GC를 강제로 발생시키는 경우는 사실상 없다고 말했기에, 이론적인 내용이라고 생각하고 접근해보려고 한다. 본인은 자바를 처음 공부할 때 이상민씨의 "자바의 신"으로 공부를 했었는데, 거기서 finalize()를 소개하면서, 절대 사용하지 말라고 (엄밀히 말하면 java.lang에 있는 finalization()이 각각의 Object의 finalize()를 실행 시킨다는 말을 하면서) 강조했었다. 사실 초보자를 위한 책인 만큼 그냥 쓰지 말라면 쓰지 말라고 생각했는데, 이번 절에서 마침 해당 내용이 나와서 좀 좋긴 했다. 일반적인 GC는 우리가 모르는 사이에 발생하지만, fi..

Programming/Java 2021.02.05

[Effective Java] item7 - 다 쓴 객체 참조를 해제하라.

다 쓴 객체 참조를 해제하라! 때는 2018년... 다른 학과였던 나는 자료구조 수업을 들었다. 사실 시험을 잘봐서 그렇지, 과제는 엉망이었다. 7번 중 0점이 2개... 눈물났다. 그땐 "아... 코딩에 재능이 없나?" 라고 생각하고 그랬었다. (지금은 재능의 문제가 아니라 노력으로 충분히 커버할 수 있는 부분이라고 생각한다!) TMI는 집어 치우고, 그때 작성했던 Stack 자료구조의 코드를 읽어보자. class Stack { private String [] data; private final int size; private int top; public Stack(int s) { data = new String[s]; size = s; top = -1; } public boolean isEmpty()..

Programming/Java 2021.02.01

[Effective Java] item6 - 불필요한 객체 생성을 피하라.

불필요한 객체 생성을 피하라! 앞에서도 여러번 이야기 했지만, 객체를 새로 만들바엔 이미 있는 객체를 재활용 하는 것이 성능이 훨씬 좋다. (정적 팩토리 메소드에서 다뤘듯이, 굳이 Boolean 생성자를 일일히 만들 바엔 valueOf를 써서 있는걸 그대로 리턴하는 것이 좋다.) public long TestCaseOne() { long beforeTime; long afterTime; beforeTime = System.currentTimeMillis(); for(int i = 0; i < 1000000; i++) { String s = new String("I'm always learning..."); s.toUpperCase(); } afterTime = System.currentTimeMillis..

Programming/Java 2021.01.28

[Effective Java] item5 - 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라.

자원을 직접 명시하지 말고 의존 객체 주입을 사용하라! 전국 피자집의 목록을 받아, 특정 지역에 있는 가게만 출력하는 클래스를 설계한다고 하자. 딱히 객체가 필요하진 않을 것 같고, 메소드만 적절히 활용하는 유틸리티 클래스를 만들어보자. import java.util.List; public class RegionFoods { private static final Food pizza = new Food(); private RegionFoods() {} // 객체 생성 방지 public static boolean isRegion(String food) {} public static List regionList() {} } 만약에 치킨집도 받고, 중국집도 받고 그래야 한다면 어떡할까? 당장 지금 생성한 클래스..

Programming/Java 2021.01.28