dsc-sookmyung / 2023-01-Effective-Java-Study

이펙티브 자바 공부하는 스터디입니다
2 stars 3 forks source link

Item59. 라이브러리를 익히고 사용하라 #54

Open Mingadinga opened 1 year ago

Mingadinga commented 1 year ago

바퀴를 다시 발명하지 말자. 아주 특별한 나만의 기능이 아니라면 누군가 이미 라이브러리 형태로 구현해놓았을 가능성이 크다. 그런 라이브러리가 있다면, 쓰면 된다. 일반적으로 라이브러리의 코드는 직접 작성한 것보다 품질이 좋고, 개선될 가능성이 크다. 코드의 품질에 규모의 경제가 적용된다.

버그가 있는 Random Int 생성

다음 코드는 범위 안에서 난수를 생성하는 코드이다. Random.nextInt()를 호출해 나머지 연산을 사용하여 범위 내의 난수를 생성한다. 이 코드에는 버그가 숨어있다.

import java.util.Random;

public class RandomBug {
    static Random rnd = new Random();

    static int random(int n) {
        return Math.abs(rnd.nextInt()) % n;
    }

    public static void main(String[] args) {
        // 버그1 : rnd.nextInt()가 Integer.MIN_VALUE를 반환하면 Math.abs도 Integer.MIN_VALUE를 반환
        int m = Integer.MIN_VALUE;
        System.out.println(Math.abs(m) % 10); // -8

        // 버그2 : 편향된 빈도수
        int n = 2 * (Integer.MAX_VALUE / 3);
        int low = 0;
        for (int i = 0; i < 1_000_000; i++)
            if (random(n) < n/2) low++;
        System.out.println(low); // 666_655

    }
}

위의 버그를 해결하려면 의사난수 생성기, 정수론, 2의 보수 계산 등을 고려해 코드를 고쳐야한다. 다행히도 이러한 부분은 Random.nextInt(n)이 해결해놓았기 때문에 직접 구현할 필요가 없다.

안전한 Random nextInt 사용

Random.nextInt(n)을 사용하면 범위 내의 난수를 안전하게 생성할 수 있다.

import java.util.Random;

public class RandomWithoutBug {

    static Random rnd = new Random();

    public static void main(String[] args) {
        int n = 2 * (Integer.MAX_VALUE / 3);
        int low = 0;
        for (int i = 0; i < 1000000; i++)
            if (rnd.nextInt(n) < n/2)
                low++;
        System.out.println(low); // 499755
    }
}

참고로 자바 7부터는 더이상 Random을 사용하지 않는 것이 좋다. ThreadLocalRandom으로 대체하면 대부분 잘 동작한다. Random보다 더 고품질의 무작위 수를 생성하고, 속도도 더 빠르다. 포크 조인 풀이나 병렬 스트림에서는 SplittableRandom을 사용한다.

라이브러리 사용의 이점 - Random nextInt

자바 표준 라이브러리

자바 프로그래머라면 적어도 이 패키지와 라이브러리에는 익숙해져야한다.

자바 표준 라이브러리 사용이 적합하지 않은 경우

전문적인 기능을 요구할수록 자바 표준 라이브러리의 기능이 충분하지 않을 수 있다.

자바 표준 라이브러리에서 원하는 기능을 찾지 못하면, 그 다음에는 고품질의 서드 파티 라이브러리를 찾아보라. 구글의 구아바 라이브러리가 대표적이다. 적합한 서드파티 라이브러리가 없다면, 다른 선택이 없으니 직접 구현해야한다.

TIP : 라이브러리에 내가 원하는 기능이 있는지 확인하려면, 메이저 릴리스의 새로운 기능을 설명하는 웹페이지를 찾아보자.