목록전체 글 (115)
도당탕탕
JNI(Java Native Interface)는 자바 프로그램에서 native method를 호출할 수 있게 해 준다. Platform specific 기능들에 접근하기 위해서 native method를 사용하는 것은 합법적이지만 대부분 그럴 필요가 없다. Java에서 이미 같은 기능을 구현한 라이브러리가 있는 경우가 대부분이기 때문이다. 예전에는 성능 최적화를 위해서, native 라이브러리를 사용하기도 했지만, 이제는 Java 라이브러리가 성능이 개선이 되었기 때문에 사용할 필요가 없어졌다. 예를 들어, BigInteger 클래스의 경우가 그렇다. Native method의 단점 메모리 corruption error에 취약해진다. garbage collector가 관리해주지 못한다. memory c..
리플렉션 기능을 이용하면 프로그램에서 임의의 클래스에 접근할 수 있다. Class객체가 주어지면 그 클래스의 생성자, 메서드, 필드에 해당하는 인스턴스를 가져올 수 있다. 또한 이 인스턴스들로는 그 클래스의 멤버 이름, 필드 타입, 메소드 시그니처 등을 가져올 수 있고 조작도 가능하다. 예를 들어 Method.invoke는 어떤 클래스의 어떤 객체가 가진 어떤 메소드라도 호출할 수 있게 해 준다. 이렇게 리플렉션을 이용하면 컴파일 당시에 존재하지 않던 클래스도 이용할 수 있는데, 다음과 같이 단점이 있다. 컴파일타임 타입 검사가 주는 이점을 하나도 누릴 수 없다. 예외 검사도 마찬가지로, 프로그램이 리플렉션 기능을 써서 존재하지 않는 혹은 접근할 수 없는 메서드를 호출하려 시도하면 런타임 오류가 발생한다..
만약 적절한 인터페이스 타입이 존재할 때, 파라미터와 리턴 타입 그리고 필드들은 모두 인터페이스 타입으로 선언되어야 한다. 이유는 더 프로그램이 더 유연해지기 때문이다. 인터페이스 사용의 장점 1. 여러 구현체 사용가능 LinkedHashSet sonSet = new LinkedHashSet(); // 유연하지 않음. Set sonSet = new HashSet(); // 유연함. 위에 코드 처럼 인터페이스 타입은 여러 구현을 사용할 수 있다. 2. 구현 클래스의 변동사항에 영향을 받지 않음. 구현 클래스 타입으로 사용시, 구현 클래스가 후에 업데이트되면, 클라이언트 코드는 더 이상 동작하지 않을 수 있다. 하지만 인터페이스는 변경될 가능성이 낮다. 적절한 인터페이스가 존재하지 않을 경우 어떻게 할까? ..
문자열 연결 연산자는 +를 사용하여 문자열들을 연결시킬 수 있다. 하지만 한 줄 자리 출력값 혹은 작고 크기가 고정된 객체의 문자열 표현을 만들 때라면 괜찮지만, 본격적으로 사용하기 시작하면 성능 저하를 일으킨다. 다음 예를 보자. 문자열 연결을 잘못 사용한 예 public String statement() { String result = ""; for (int i = 0; i < numItems(); i++) { result += lineForItem(i); } return result; } 위 예제에서 문자열 연결 연산자를 사용했다. 하지만 이 메서드는 심각하게 느려지는 현상을 볼 수 있다. 그 이유는 문자열 연결 연산자는 문자열 n개를 잇는 시간이 n^2에 비례하기 때문이다. 문자열은 불변이기 때문..
보통 파일이나 네트워크로부터 데이터가 넘어오면, String 형태의 데이터인 경우가 많다. 하지만 이를 그대로 String 변수에 저장하기보다 적절한 자료형으로 저장하는 것이 좋다. String은 aggregate type을 표현하기 에는 부적절하다. String compoundKey = className + "#" + i.next() 위 처럼 표현하면 결국, className을 뽑아내기 위해서는 String을 파싱 해야 한다. 그보다는 item 24에서 배웠듯이 static class 를 사용해서 표현하는 것이 좋다. private static class CompoundKey { String className; String next; public CompoundKey(String className, S..
자바의 데이터 타입은 크게 두 가지로 나뉜다. 원시 타입 : int, double, boolean 참조 타입 : Integer, Double, Boolean 오토박싱과 오토언박싱 덕분에 두 타입을 크게 구분하지 않고 사용할 수는 있지만, 그렇다고 차이가 사라지는 것은 아니다. 둘 사이의 분명한 차이는 있으니 적절히 사용해야 한다. 기본 타입과 박싱 된 기본 타입의 주된 차이는 크게 세 가지이다. 기본 타입은 값만 가지고 있으나, 박싱 된 기본 타입은 값에 더해 식별성이란 속성을 갖는다. 달리 말하면 박싱된 기본 타입의 두 인스턴스는 값이 같아도 서로 다르다고 식별될 수 있다. 기본 타입의 값은 언제나 유효하나, 박싱된 기본 타입은 유효하지 않는 값, 즉 null을 가질 수 있다. 기본 타입이 박싱된 기본..
float, double의 문제점 float 과 double 타입은 주로 과학적, 공학적 계산에 사용되도록 설계되었다. 하지만 항상 정확한 수치를 리턴하지는 않는다. 특히 환율계산 작업에는 적합하지 않다. 왜냐하면 0.1을 정확히 표현하는 것이 불가능하기 때문이다. System.out.println(1.03 - 0.42) 위의 결과는 0.6100000000000001 이다. 그리고 System.out.println(1.00 - 9 * 0.10); 위의 결과는 0.09999999999999998 이다. 단지 반올림 함으로써 문제를 해결할 수 있다고 생각하지만, 항상 그렇게 할 수 있는 것은 아니다. 다음은 10 cent,20 cent,30 cent,..., 1 dollar까지 candy 값을 올려가며, 최..
무작위 정수 하나를 생성하는 문제가 심각한 코드 static Random rnd = new Random(); static int random(int n) { return Math.abs(rnd.nextInt()) % n; } // 무작위 수 100만개를 생성한 다음, 그중 중간 값보다 작은 게 몇 개인지를 출력하는 코드 public static void main(String[] args) { int n = 2 * (Integer.MAX_VALUE / 3); int low = 0; for (int i = 0; i < 1000000; i++) { if (random(n) < n / 2) low++; System.out.println(low); } } 위 코드에서는 3가지 문제가 있다. n이 그리 크지 않은 ..