Programming 29

[Effective Java] item19 - 상속을 고려해 설계하고 문서화하라. 그러지 않았다면 상속을 금지하라!

상속을 고려해 설계하고 문서화하라. 그러지 않았다면 상속을 금지하라!개발을 할 때 상속이 편리한 친구이긴 하지만, 외부 클래스를 상속하는 과정에서 발생하는 문제들도 분명 있다. 그렇기에 상속을 할 가능성을 조금이라도 열어놓는다면 문서화를 해 두는 것을 권장한다.일반적으로 상속을 하면 가장 먼저 하는 것 중에 하나가 메소드 재정의일 것이다. 그러나 상속을 하는 사람들이 이 메소드의 구체적인 역할이 무엇인지 판단해야 하므로, 상속용 클래스는 재정의할 수 있는 메소드들을 내부적으로 어떻게 이용하는지 문서로 남길 필요가 있다. 구체적으로 어떤 순서로 내부 과정이 이뤄지는지, 각각의 결과가 어떤 결과를 만들어내는지 까지 작성하면 좋다.자바 API 문서의 메소드 설명을 보면, 가끔 특이한 문구가 붙어있다.Imple..

Programming/Java 2021.03.08

[KAKAO BLIND 2020] - 가사 검색

이 문제의 정해는 트라이로 알려져 있는데, 개인적으로는 코테를 준비하기 위해 트라이를 배우는 것은 권장하지 않는다. 카카오 블라인드에서 트라이로 풀 수 있는 두 문제는 모두 트라이가 아닌 다른 방법으로 해결할 수 있고, 코드도 훨씬 짧다. 실제로 코딩테스트 과외를 할 때도 절대 이 문제를 트라이로 풀 생각을 하지 말라고 말했고, 아래 풀이는 수업을 하면서 실시간으로 작성한 코드이다. 어차피 가능한 경우는 AAA??나 ??AAA 같이, 앞과 뒤에 ?가 붙는 문자들이다. 그런데 생각해보자. AAA??는 AAAAA, AAAAB, .... AAAZY, AAAZZ가 가능할 것이다. 그렇다면 이것은 AAAAA ~ AAAZZ 의 사이에 들어있는 문자를 모두 검색하면 되는 것이고, 다시 말해서 (AAAZZ의 upper..

[Effective Java] item15 - 클래스와 멤버의 접근 권한을 최소화하라.

클래스와 멤버의 접근 권한을 최소화하라! 객체지향의 요소를 떠올리면, 캡슐화 (Encapsulation) 이라는 말이 있다. 해당 요소의 의미는 프로그램 내 같은 기능을 목적으로 작성된 코드를 모아서 보이지 않게 숨기는 것을 의미한다. 그런데 왜 캡슐화를 해야할까? 객체지향적인 이야기이긴 하지만, 몇 가지 장점을 생각해보자. 여러 컴포넌트를 병렬로 개발할 수 있기 때문에 개발 속도를 향상시킨다. 컴포넌트를 변경할 수 있고, 특정 컴포넌트를 분리해서 디버깅 할 수 있다. 다른 컴포넌트와 분리되어 있는 만큼, 성능 최적화를 위해선 특정 컴포넌트만 떼어서 최적화 하기에도 편하다. 독자적으로 동작하는 컴포넌트를 개발했으면, 해당 컴포넌트를 다른 프로젝트에서도 사용할 수 있기 때문에 재사용성이 올라간다. 시스템을..

Programming/Java 2021.02.18

[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

백준 문제 풀이 (2.1 ~ 2.8)

시간은 안나지만 최대한 시간을 투자해서 문제를 풀려고 노력하고는 있다.... 푼 문제 중에서 플레급 문제만 적어보았다. #9345 - 디지털 비디오 디스크 (DVDs) 재밌는 세그먼트 트리 문제였다. 임의의 칸 두개를 지정하고, 해당 범위의 값을 구한다고 가정해보자. 순서에 상관없이 값만 존재하면 OK이기 때문에, 구간을 대표할 수 있는 값을 찾아야 할 것이다. 간단하게 생각해보면 구간합/최댓값/최솟값이 있을텐데, 곰곰히 생각해보면 최댓값/최솟값 두개만 있으면 해결할 수 있다. 예를 들어, 2~6번째 칸의 최댓값이 6이고, 최솟값이 2라면 그 사이의 값은 반드시 3, 4, 5라는 것이 보장된다. 따라서 최댓값 세그먼트 트리, 최솟값 세그먼트 트리를 각각 만들어서 해결하면 된다. #16975 - 수열과 쿼..

[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