Post

(Effective Java) 9장 일반적인 프로그래밍 원칙 (TIP - String 비교, 문자열 포매팅)

아이템 57. 지역번수의 범위를 최소화하라

아이템 58. 전통적인 for 문 보다는 for-each 문을 사용하라

  • for-each를 사용하지 못하는 경우가 있긴 하다.
    • 루프 돌면서 원소 찾아서 제거해야 하는 경우.
      • 근데 요즘은 for문 돌지 말고 removeIf()를 사용하는 것을 권장함.
    • 루프 돌면서 원소를 변경해야 하는 경우. (인덱스로 접근해야 하는 경우)
    • 병렬로 돌아야 할 때

아이템 59. 라이브러리를 익히고 사용하라

  • 웬만한건 라이브러리에 다 있으니 잘 찾아보고 써라. 이게 대체로 직접 짜는 것 보다 퀄리티도 더 낫다.
  • 그리고 라이브러리 쓸거면 제대로 알아보고 써라. 막 쓰지 말고.

아이템 60. 정확한 답이 필요하다면 float와 double은 피하라

  • 대신 BigDecimal, int, long을 써라~
    • 소숫점 자리수랑, 숫자랑 분리해서 저장해서 정수를 사용하거나
    • 아니면 소숫점 이하 자리수가 고정되어 있으면 *100 한 정수값을 사용하거나.
    • 아무튼 정수를 사용하는 것이 좋다. 돈 계산에서는 무조건.
  • 실수(float, double) 비교는 == 말고 .compare()를 사용한다.
    • Float.NaN, -0.0f 및 특수한 부동소수 값 등을 다뤄야 하기 때문.
  • 참고로 BigDecimal 쓸 때, equals는 value와 scale이 모두 동일해야 true가 반환된다. value만 보려면 compareTo를 사용해야 한다.

아이템 61. 박싱된 기본 타입 보다는 기본 타입을 사용하라

  • 속도 때문에 그런것도 있고
  • 실수할 여지가 늘어난다.
    • 박싱된 기본 타입에 ==을 쓰면 객체의 주소 비교 가 일어나서 값이 같아도 다르다는 결과가 나온다.

아이템 62. 다른 타입이 적절하다면 문자열 사용을 피하라

  • 당연.. 문자열에 다 때려 넣어서 substring해서 쓰거나, enum개념이 명확한걸 문자열로 쓰거나 하는 것은 지양하는 것이 좋지.

아이템 63. 문자열 연결은 느리니 주의하라

  • String 연결할 때 + 연산자 써서 연결하게 되면 느리니까, StringBuilder를 사용해라 라는 내용인데…
    • 프로파일링 해보니 + 연산자는 Arrays.copyOf()가 호출되면서 복사가 일어나기 때문에 매번 새로운 String 객체를 만들면서 문자열을 조합하기 때문에 느리다.
    • 반면 StringBuilder고정길이 Buffer에 문자열을 붙여 나가다가 한 번에 toString으로 전환하기 때문에 훨씬 빠르다
  • 하지만 단순 문자열 더하기라면, + 연산자를 써도 컴파일러가 StringBuilder 로 자동 변환해준다!!

    • 그러나 모든 경우 이런 변환이 일어나는 것은 아니다.
    • 예를 들어, 반복문 내부에는 반드시 StringBuilder를 써야 한다. + 연산이 빌더로 자동 변환되지 않아 매우 느리기 때문.
  • 문자열 몇 개 연결하는 정도는 성능에 큰 차이가 안나므로, 취향에 따라 선택 가능하다.
  • StringBuilder vs joining
    • iter 방식으로 문자열 만들 때는 StringBuilder 가 유용.
    • stream 방식으로 문자열 만들 때는 joining 이 유용.

비교? StringUtils를 쓰는게 보기 더 깔끔하다

1
2
3
4
StringUtils.equals(certification.getMobileOs(), "ios")
certification.getMobileOs().equals("ios")
길이는 위에가  길지만,  가독성이 좋다.
+++ NPE 방지도 된다.

문자열 포매팅

1
2
3
4
5
6
7
8
// {} 방식 문자열 포매팅
String pattern = "{0} - {1} | {2}";
Object[] arguments = {"LOG", "key1", "value1"};

String result = MessageFormat.format(pattern, arguments);

// printf-style(%) 문자열 포매팅
String.format()

하지만 + 보다 속도가 꽤나 느려서 꼭 필요할 때만 사용하는 것이 좋음.

Url 관련 스트링은 UriComponentsBuilder 를 사용할 수 있음.

  • buildAndExpand() 에서 파라미터를 순서 기반으로 매칭하는 것과, Map을 넘기는 것이 가능한데… 순서기반 매칭은 내재된 fragile함이 있음.
  • queryParam() 사용하는 것은 좋음. 단순 String 연결 보다 가독성에서 이점이 있음.
  • https://www.baeldung.com/spring-uricomponentsbuilder
    • 그 외에도 regex로 Uri를 만들면서 validation 할 수 있음. 큰 장점.

아이템 64. 객체는 인터페이스를 사용해 참조하라

  • 당연함. 인터페이스를 통해 참조해야 유연성을 확보할 수 있고, 의존성을 낮출 수 있으니까
  • 다만 클래스가 1개 뿐이고 더 늘어날 가능성도 거의 없는데 인터페이스로 참조하겠다고 인터페이스를 또 만드는 것은 비추. 소스트리만 지저분해짐

아이템 65. 리플렉션보다는 인터페이스를 사용하라

  • 리플렉션은 강력한 기능이지만 단점이 많다
    • 컴파일타임 타입 검사가 불가능하다. 리플렉션은 런타임에 정보를 가져오고자 하는거니까
    • 아무래도 코드가 지저분해진다.
    • 성능이 떨어진다. 리플렉션을 통해서 Method.invoke()하는건 일반 호출보다 느리다.
  • 그래서 꼭 필요한 경우에만 쓰자.
  • 리플렉션을 통해서 반환받은 객체는 인터페이스나 상위 클래스에 담아서 type safety하게 다루자

아이템 66. 네이티브 메서드는 신중히 사용하라

  • 당연함. 성능이나 native api가 아니라면 써야 할 이유도 없고, 네이티브로 간다고 해서 성능이 무조건 좋아지리라는 법도 없어 공수도 많이 들고, 유지보수도 어렵고, 호환성도 떨어짐… 꼭 필요한 경우가 아니라면 보통 안쓰지

아이템 67. 최적화는 신중히 하라

  • 최적화를 할 때는 다음 두 규칙을 따르라.
    • 첫 번째, 하지 마라.
    • 두 번째, 아직 하지 마라.
    • 그니까, 완전히 명백하고 최적화되지 않은 해법을 찾을 때 까지는 하지 마라.
  • time complexity로 접근하는 알고리즘 개선은 효과가 있는 경우가 대부분이나, 다른 부분의 최적화는 글쎄.

    • 요즘은 컴퓨팅 파워도 그렇고 컴파일러 최적화도 많이 좋아져서, 최적화 한답시고 투자하는 리소스 대비 크게 효율 개선이 되지 않을 수도 있음 ㅜㅜ
  • 빠른 프로그램 보다는 좋은 프로그램을 작성하라!
    • 객체 지향 원칙에 따라 잘 디커플링 된 좋은 프로그램이라면, 최적화 할 때도 쉽게 접근할 수 있다.
    • 좋은 프로그램이면 보통 성능도 잘 나온다

아이템 68. 일반적으로 통용되는 명명 규칙을 따르라

This post is licensed under CC BY 4.0 by the author.