Object클래스의hashCode()는반환 타입이int입니다.32bit JVM 에서
64bit JVM으로 넘어가면서long타입의hash code를 사용하는 것이 맞지만기존의 int 타입을 유지하는 것을 선택했습니다.그 이유는 Java 가
backward compativility를 중요하게 생각하기 때문입니다.결과적으로
hash collision이 발생할 확률이 증가했습니다.hashCode() 를 사용할 때에는
overriding하여 사용하는 것을 권장합니다.
깊은 복사가 필요할 때Cloneable을 사용하면 됩니다.
Cloneable인터페이스의clone()은Object를반환함으로써모든 사용자 정의 클래스가 사용할 수 있습니다.Cloneable 을 구현하면
clone()의결과를down-casting하여 사용하면 됩니다.그러나 객체를 복사한다는 의미에서 다른 타입의 객체를 반환할 일이 없습니다.
- 편의를 위해
Covariant Return Type을 지원합니다.Overriding할 때 조상 메서드의반환타입을 그자손 타입으로 재정의 할 수 있습니다.- Cloneable 에 국한되지 않고 모든 overriding 상황에서 사용할 수 있습니다.
Java 의 소스코드를 보다 보면
native가 붙은빈 메서드를 찾을 수 있습니다.
이는 시스템 수준의 작업이나 하드웨어 작업을 위해 C/C++ 과 같은native language로 작성된 메서드입니다.
native 메서드는호출을 위해시그니처를 선언해 둔 것일 뿐 overriding 할 필요가 없습니다.
String은immutableobject(불변 객체) 입니다.
따라서 변경이 불가능하고, 변경이 필요할 때 마다COW(copy on write)합니다.
- Java 는 성능 향상을 위해
String Pool을 사용합니다.문자열 literal들을컴파일시점에 최적화 하고 String pool 에 저장하고 그 문자열이 사용될 때마다String Pool에서 제공합니다.- 런타임에
동적으로 생성되는 문자열은 String Pool 에 저장되지 않습니다.- 비슷하게
Integer,Long,Short,Byte,Character,Boolean도cache를 가지고 있습니다.
String a = "a";
String b = "b";
String aplusb = "a"+"b";
String ab = "ab";
if (aplusb == a + b) {
System.out.println("ab == a + b");
} else {
System.out.println("ab != a + b"); // result
}
if (ab == aplusb) {
System.out.println("ab == aplusb"); //result
} else {
System.out.println("ab != aplusb");
}
String target = "0";
while (true) {
String s = String.valueOf((int) (Math.random()*10));
System.out.println(target + " == " + s);
if (s == target) { // never be true
System.out.println("Found!");
break;
}
}
- Java 의
ClassLoader는class loading시점에.class 파일을 읽어서Class 객체를 생성하고 저장해둡니다.- 이 Class 객체에는
설계도처럼 클래스에 대한정보가 모두 담겨있습니다.Class 객체를 얻는 방식은 다음과 같습니다.
Class c = new MyClass.getClass();
Class c = MyClass.class;
Class c = Class.forName("MyClass");
forName()을 사용하면런타임에동적으로 클래스 정보를 얻어내는 것이 가능합니다.Reflection API와 함께 동적으로 여러가지 일 들을 할 수 있습니다.
StringBuffer혹은StringBuilder는 잦은 변경이 필요한 문자열을 다룰때 사용됩니다.
- String 과는 다르게
equals()메서드가 오버라이딩 되어있지 않습니다.- StringBuffer 나 StringBuilder 로 작업했던 문자열은
등가 비교를 할 때 반드시String으로변환해서 비교해야 합니다.
Math클래스의 유틸리티 메서드 들은최적화를 위해하드웨어나OS라이브러리를 사용합니다.
따라서환경에 따라다른 결과를 얻을 수 있습니다.
플랫폼 독립적인계산 결과가 필요하다면StrictMath클래스를 사용합니다.
Number추상 클래스를 상속받은 클래스들 중에 Wrapper 클래스 외에도BigInteger,BigDecimal클래스가 있습니다.
배열을 활용해매우 큰 수를 다루므로 효율적입니다.
BigDecimal을 생성할 때literal 실수를 사용하면오차가 생길 수 있습니다.- 생성자의 인자는 반드시
문자열을 사용합니다.
BigDecimal fromLiteral = new BigDecimal(0.1);
BigDecimal fromString = new BigDecimal("0.1"); // accurate
유틸리티 클래스
Objects에는 유용한 메서드들이 있습니다.
equals()
- Object.equals() 와 달리 null 체크를 해줍니다.
if (a != null && a.equals(b)) { /*...*/ } // can be simplified like this if (Objets.equals(a, b)) { // no need to check a or b is null /*...*/ }
deepEquals()
- 다차원 배열 등가 비교에 사용합니다.
requireNonNull()
- 유효성 검사를 간단하게 할 수 있습니다.
void setName(String name) { if (name == null) { throw new NullPointerException("name must not be null"); } this.name = name; } // can be simplified like this void setName(String name) { this.name = Objects.requireNonNull(name, "name must not be null"); }
compare()
- Object 에는 없는 대소 비교 기능을 제공합니다.