float와 double 연산은 정확하지 않다. (특히 금융 관련 계산과는 맞지 않음) double result = 1.03 - 0.42; System.out.println(result); // 0.6100000000000001 위와 같은 단순한 계산에도 오차가 발생한다. → float와 double은 부동소수점 방식을 사용하기 때문 부동소수점 방식 부동소수점 방식은 수를 정수와 실수로 구분하지 않고 지수부와 가수부로 구분한다. 소수점이 고정되지 않기 때문에 더 폭넓은 범위를 표현할 수 있지만, 필연적으로 오차가 발생하여 근사값을 구한다. 해결 방법 1) BigDecimal double 타입을 BigDecimal 을 사용하면 실수 연산을 오차없이 사용할 수 있다. BigDecimal은 기본 타입보다 쓰기..
static Random rnd = new Random(); static int random(int n){ return Math.abs(rnd.nextInt()) % n; } public static void main(String[] args) { 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); } 위 코드는 무작위 정수를 하나를 생성하는 코드인데 문제점이 많다. n이 그리 크지 않은 2의 제곱수라면 얼마 지나지 않아 같은 수열이 반복된다. n이 2의 제곱수가 아니라면 몇몇 숫자가 평균적으로 더 자주 반환된..
전통적인 for문 //컬렉션 순회하기 for (Iterator i = c.iterator(); i.hasNext()) { Element e = i.next(); // ... } //배열 순회하기 for (int i = 0; i < a.length; i++) { // ... } 위 for문은 while문보다는 낫지만 [아이템 57] 가장 좋은 방법은 아님 반복자와 인덱스 변수는 코드를 지저분하게 함 → 우리에게 정말 필요한건 원소들뿐 요소 종류가 늘어나면 오류 가능성이 높아짐 컬렉션이냐 배열이냐에 따라 코드 형태가 매우 달라짐 for-each 문 //컬렉션 순회하기 for(Element e : elements) { // ... } //배열 순회하기 for(int i : a) { // ... } for-ea..
지역변수의 유효 범위를 최소로 줄이면 코드 가독성과 유지보수성이 높아지고 오류 가능성은 낮아짐 지역변수 범위를 줄이는 방법 1) 가장 처음 쓰일 때 선언하기 사용하려면 멀었는데, 미리 선언부터 해두면 코드가 어수선해져 가독성 떨어짐 범위를 제대로 제한하지 않으면 이미 사용한 뒤에도 할당 해제가 되지않고 힙 메모리에 유지됨 2) 거의 모든 지역변수는 선언과 동시에 초기화해야함 초기화에 필요한 정보가 충분하지 않다면 그때까지 선언을 미뤄야함 try-catch 문은 예외 : 변수 초기화 과정에서 검사 예외를 던질 가능성이 있다면 try 블록안에서 초기화해야함 반복문 : for, for-each 문은 반복 변수의 범위가 반복문 블록 안으로 제한됨 → 반복 변수의 반복문이 종료된 이후에도 써야하는 게 아니면 wh..
자바독 (Javadoc) API를 쓸모 있게 하기 위해 문서화가 잘 되어있어야함 API 문서화 유틸리티 소스코드 파일에서 문서화 주석(자바독 주석)이라는 특수한 형태로 기술된 설명을 추려 API 문서로 변환해준다. 자바 프로그래머라면 자바독 주석을 작성하는 규칙을 알아야함 Javadoc 주석 유의사항 API를 올바로 문서화하기 위해선 공개된 모든 클래스, 인터페이스, 메서드, 필드 선언에 문서화 주석을 달아야함 주석을 달지 않으면 그저 공개된 API 요소들의 선언만을 나열 공개 클래스는 기본 생성자에 주석을 달 수 있는 방법이 없으니 절대 기본 생성자를 사용하지마라. 유지보수까지 고려한다면 공개되지 않은 것들에도 문서화 주석을 달아야할 것이다. 메서드용 문서화 주석에는 해당 메서드와 클라이언트 사이의 규..
자바8 이전 자바8 이전에는 메서드가 특정 조건에서 값을 반환할 수 없을 때 두가지 선택지가 있었다. 예외 던지기 예외는 진짜 예외적인 상황에서만 사용해야함 예외를 생성할 때 스택 추적 전체를 캡쳐하므로 비용이 큼 반환 타입이 객체 참조라면 null 반환 클라이언트에서 null을 반환하는 메서드를 호출할 때 추가적으로 null 처리 코드를 작성해야함 //컬렉션에서 최대값을 구함 - 컬렉션이 비었으면 예외 던지기 public static E max(Collection c) { if (c.isEmpty()) throw new IllegalArgumentException("Empty collection"); E result = null; for (E e : c) if (result == null || e.co..
빈 컬렉션 반환 //컬렉션이 비었다면 null을 반환 -> 따라하지 말 것 public List getCheeses() { return cheesesInStock.isEmpty() ? null : new ArrayList(cheesesInStock); } 만약 위와 같이 코드를 작성하였다면, 클라이언트는 이 null 상황을 처리하는 코드를 추가로 작성해야한다. List chesses = shop.getCheeses(); if(cheeses != null && chesses.contatins(Cheese.STILTON)) System.out.println("ok"); 컬렉션이나 배열이 비었을 때 null을 반환하는 메서드를 사용할 때면 항상 이렇게 방어 코드를 넣어줘야 한다. 만약 방어 코드를 까먹으면 오..
가변인수 메서드 명시한 타입의 인수를 0개 이상 받을 수 있는 메서드 가변인수 메서드를 호출하면 먼저 인수 개수와 길이가 같은 배열을 만들고 이 배열에 저장하여 가변인수 메서드에 건네줌 static int sum(int... args) { int sum = 0; for (int arg : args) { sum += arg; } return sum; } // 인수가 꼭 1개 이상이어야할때 static int min(int firstArg, int... remainArgs) { int min = firstArg; for (int arg : remainArgs) { if(arg < min) min = arg; } return min; } 가변인수는 인수 개수가 정해지지 않았을 때 매우 유용함. ex) prin..