Object class
java.lang 패키지
java.lang.*은 컴파일 할때 자동으로 추가된다.
모든 클래스의 최상위 클래스 Object
Object클래스는 모든 자바 클래스의 최상위 클래스다.
모든 클래스는 Object 클래스로부터 상속을 받는다.
클래스를 만들때 extends Object를 하지 않지만, 컴파일 과정에서 자동으로 들어간다.
모든 클래스가 Object 클래스를 상속 받았으므로 Object의 메소드를 사용할 수 있고 재정의 할 수도 있다
주로 사용되는 Object클래스의 메소드
String toString() : 객채를 문자열로 표현하여 반환한다. 재정의하여 객체에 대한 설명이나 특정 맴버변수 값을 반환한다.
boolean equals(Object obj) : 두 인스턴스가 동일한지 여부를 반환한다. 재정의하여 논리적으로 동일한 인스턴스임을 정의한다.
int hashCode() : 객체의 해시 코드 값을 반환한다.
Object clone() : 객체를 복제하여 동일한 멤버 변수를 가진 새로운 인스턴스를 생성한다.
Class getClass() : 객체의 Class 클래스를 반환한다.
void finalize() : 인스턴스가 힙 메모리에서 제거될 떄 GC에 의해 호출되는 메소드. 네트웍 연결 해제, 열려있는 파일 스트림 해제 등을 구현한다.
void wait() : 멀티스레드 프로그램에서 사용한다. 스레드를 non runnable로 만든다.
void notify() : wait() 메소드에 의해 no runnable를 runnable로 가져온다.
toString() 메소드
toString() 메소드는 인스턴스의 정보를 문자열로 반환하는 메소드다. toString()의 원형은 인스턴스의 클래스 이름과 주소값을 보여준다.
toString()의 원형
java 복사 getClass ().getName () + '@' + Integer.toHexString (hashCode ())
String과 Integer의 경우는 toString()을 호출해도 원형대로 반환하지 않는다. 이미 오버라이딩 되어있기 때문이다.
equals() 메소드
두 인스턴스의 주소값을 비교하여 boolean값을 반환해준다.
주소값이 같다면 당연히 같은 인스턴스다.
하지만 다른 주소값을 가지더라도 논리적으로 같은 인스턴스라고 판단해야 할 때가 있다.
equals()의 재정의
java 복사 class Student {
int studentId;
String studentName;
public Student (int studentId, String studentName) {
this .studentId = studentId;
this .studentName = studentName;
}
@Override
public boolean equals (Object obj) {
if (obj instanceof Student) {
Student std = (Student) obj;
if (this .studentId == std.studentId) {
return true ;
} else {
return false ;
}
}
return false ;
}
public String toString () {
return studentId + ", " + studentName;
}
}
public class EqualsTest {
public static void main (String[] args) {
Student student1 = new Student (100 , "KANG" );
Student student2 = new Student (100 , "KANG" );
System.out.println (student1 == student2);
System.out.println (student1.equals (student2));
}
}
hashCode() 메소드
Hash는 정보를 저장하거나 검색할때 사용하는 자료구조다. 정보를 어디에 저장할 것인지, 어디서 가져올 것인지 해시 함수를 사용해 구현한다. 해시 함수는 객체의 특정정보를 매개변수 값으로 넣으면 그 객체가 저장되어야 할 위치 나 저장된 해시 테이블 주소 를 반환한다.
자바에서는 인스턴스를 힙 메모리에 생성하여 관리할 때 해시 알고리즘을 사용한다.
java 복사 hashCode = hash (key);
hashCode로 출력되는 15진수 숫자값은 JVM이 힙 메모리에 저장한 인스턴스의 주소값 이다.
두 인스턴스가 같다면 hashCode()의 반환값도 같아야한다.
논리적으로 같은 두 객체를 위해 hashCode()를 오버라이딩 할 필요가 있다.
clone() 메소드
객체 원본을 유지해놓고 복사본을 사용하거나, 기본 프로토타입의 복사본을 사용해 동일한 인스턴스를 만들어 복잡한 생성과정을 간단하게 할때 사용한다.
객체를 복제해 또 다른 객체를 반환해 준다.
clone()으로 인스턴스를 복제하는 예제
java 복사 class Point {
int x;
int y;
Point (int x, int y) {
this .x = x;
this .y = y;
}
public String toString () {
return "x = " + x + ", y = " + y;
}
}
class Circle implements Cloneable {
Point point;
int radius;
Circle (int x, int y, int radius) {
this .radius = radius;
point = new Point (x, y);
}
@Override
public String toString () {
return "Circle{" +
"point=" + point +
", radius=" + radius +
'}' ;
}
@Override
public Object clone () throws CloneNotSupportedException {
return super .clone ();
}
}
public class CloneTest {
public static void main (String[] args) throws CloneNotSupportedException {
Circle circle = new Circle (10 , 20 , 30 );
Circle copyCircle = (Circle) circle.clone ();
System.out.println (circle);
System.out.println (copyCircle);
System.out.println (System.identityHashCode (circle));
System.out.println (System.identityHashCode (copyCircle));
}
}
clone() 메소드를 사용하려면 객체를 복제해도 된다는 의미로 Cloneable 인터페이스를 구현해야한다.
Object의 clone()은 클래스의 인스턴스를 새로 복제하여 생성해준다. 맴버젼수가 동일한 인스턴스가 다른 메모리에 새로 생성되는 것이다.
String class
java 복사 String str1 = new String ("test" );
String str2 = "test" ;
String str3 = "test" ;
new String으로 생성된 문자열은 새로운 메모리가 할당되고 인스턴스 된다.
상수를 바로 가리키는 경우에는 상수 풀을 참조하게 된다.
StringBuffer와 StringBuilder 활용
StringBuffer와 StringBuilder는 내부에 변경 가능한 char[]를 변수로 가지고 있다.
문자열을 연결하면 기존에 사용하던 char[]배열이 확장되 메모리를 낭비하지 않는다.
두 클래스의 큰 차이는 아래와 같다
StringBuffer : 문자열이 안전하게 변경되도록 멀티스레드에서 보장된다.
StringBuilder : 멀티스레드에서 작업이 보장되지 않지만 실행속도가 빠르다.
java 복사 public class StringBuilderTest {
public static void main (String[] args) {
String javaStr = new String ("Java" );
System.out.println (System.identityHashCode (javaStr));
StringBuilder buffer = new StringBuilder (javaStr);
System.out.println (System.identityHashCode (buffer));
buffer.append (" jammy" );
buffer.append (" it-da!" );
System.out.println (System.identityHashCode (buffer));
javaStr = buffer.toString ();
System.out.println (javaStr);
System.out.println (System.identityHashCode (javaStr));
}
}
String.intern()
String.intern()
String에 intern() 이라는 메서드가 있는데, 변수 문자열값에 대해 상수풀을 뒤져서 상수풀에 존재하면 그걸 반환함
Wrapper class
기본자료형을 클래스로 씌워놓은것을 wrapper class라고 한다.
기본 자료형을 위한 클래스
primitive을 클래스로 써야하는 경우
매개변수가 객체거나 반환 값이 객체형인 경우
제네릭의 반환 타입을 지정할때 (자바 언어 스팩)
오토박싱과 언박싱
오토박싱 : primitive 타입을 reference타입으로 바꾸는 것
언박싱 : reference 타입을 primitive타입으로 바꾸는 것
Class class
자바의 모든 클래스와 인터페이스는 컴파일 되고 나면 class파일로 생성된다.
Class클래스는 컴파일 된 class 파일에 저장된 클래스나 인터페이스 정보를 가져오는데 사용된다.
코드를 작성할때 사용하는 여러 클래스의 모든 정보를 알고있는것은 아니다 (필요한 매개변수 또는 반환타입)
이런 경우 정보를 알고싶을때 Class 클래스를 활용한다.
Object 클래스의 getClass()활용
java 복사 String s = new String ();
Class c = s.getClass ();
클래스 파일 이름을 Class변수에 직접 대입하기
java 복사 Class c String.Class;
Class.forName("CLASS_NAME") 사용하기
java 복사 Class c = Class.forName ("java.lang.String" );
c.getConstructors (); // 모든 생성자 가져오기
c.getFields (); // 모든 멤버 변수 가져오기
c.getMethods (); // 모든 메소드 가져오기
Reflection programming
Class 클래스를 사용하는 방법은 클래스의 자료형을 직접 사용하여 프로그래밍 하는 것 보다 더 복잡하고 예외처리도 해야 한다. 이미 우리가 자료형을 알고 있는 클래스인 경우 또는 컴파일 할 때 직접 참조 할 수 있는 클래스는 Class 클래스를 활용할 필요가 없다. 클래스의 정보를 모두 알고 있는 상황에서 리플렉션 프로그래밍을 하면 오히려 코드가 복잡해지고 속도도 느려진다.
따라서 리플렉션 프로그래밍은 컴파일 시점에 알 수 없는 클래스, 즉 프로그램 실행 중에 클래스를 메모리에 로딩 하거나 객체가 다른 곳에 위치해서 원격으로 로딩하고 생성할 때 사용한다.
Reflection 글 모음