본문 바로가기

# 02/Java

[윤성우 열혈자바] 19-2. Object 클래스

반응형

Object 클래스의 finalize 메소드


protected void finalize() throws Throwable


Object 클래스에 정의되어 있는 이 메소드는 인스턴스 소멸 시(JVM에 의해 가비지 컬렉션 작동 시) 자동으로 호출이 된다. 단, 가비지 컬렉션이 자주 작동하면 자바 성능이 저하 될 수 있어 가상머신이 알아서 동작한다.

따라서 finalize 메소드가 언제 실행될지 예측 할 수 없어 사용하지 않는다. 사용 안되고 프로그램이 종료 될 수도..


자식 클래스에서 오버라이딩 할 수 있음.








finalize 메소드의 오버라이딩 예


class Person {

String name;


public Person (String name) {

this.name = name;

}


@Override

protected void finalize() throws Throwable {

super.finalize();                                // 상위 클래스의 finalize 메소드 호출

System.out.println( "destroyed : " + name );

}

}



public  static void main (String[] args) {

Person p1 = new Person("Yoon");

Person p2 = new Person("Park");

p1 = null;            // 참조대상을 가비지 컬렉션의 대상으로 만듦

p2 = null;            // 참조대상을 가비지 컬렉션의 대상으로 만듦


// System.gc();

// System.runFinalization();


System.out.println("end of program");

}


위의 상황에서는 가비지 컬렉션이 작동하지 않음.


GC는 프로그램을 실행할 때 메모리 공간을 운영하기 위해 작동하는데 자바 프로그램이 종료되는 상황에서는 모든 메모리들이 사라지기 때문에 굳이 GC 할 필요가 없음. 그래서 GC 동작안함!


즉, finalize는 사용하지 않음. 상징적인 메소드 일뿐!




다음 메소드는 일반적인 상황이 아닌 임베디드나 제한된 메모리 일 때만 활용한다.


System.gc();                // GC 재촉하는 메소드, 단 호출될 수도 있고 안 될 수도 있음!

System.runFinalization();    // GC 요청. 두 가지 요청하면 대부분 GC 발생함!








인스턴스의 비교 : equals 메소드


class INum {

private int num;

public INum ( int num ) {

this.num = num;

}


@Override

public boolean equals(Object obj) {

if ( this.num == ((INum)obj).num )

return true;

else

return false;

}

}



public static void main (String[] args) {

INum num1 = new INum(10);

INum num2 = new INum(12);

INum num3 = new INum(10);


if( num1.equals(num2) )

System.out.println( "num1, num2 내용 동일하다." );

else

System.out.println( "num1, num2 내용 다르다." );


if( num1.equals(num3) )

System.out.println( "num1, num3 내용 동일하다." );

else

System.out.println( "num1, num3 내용 다르다." );

}


인스턴스의 내용 비교를 위한 기능을 equals 메소드에 담아 정의한다.


equals는 Object 클래스의 메소드이다.








String 클래스의 equals 메소드


public static void main (String[] args) {


String str1 = new String("So Simple");

String str2 = new String("So Simple");


// 참조 대상을 비교하는 if ~ else 문

if (str1 == str2 )

System.out.println("str1, str2 참조 대상 동일하다.");

else

System.out.println("str1, str2 참조 대상 다른다.");


// 두 인스턴스 내용 비교하는 if ~ else 문

if (str1.equals(str2))

System.out.println("str1, str2 내용 동일하다.");

else

System.out.println("str1, str2 내용 다르다.");


}



String 클래스는 내용 비교를 하는 형태로 equals 메소드를 오버라이딩 하고 있음!!!!








인스턴스 복사 : clone 메소드


protected Object clone() throws ColneNotSupportedException


Object 클래스에 정의되어 있는 clone 메소드가 호출되면 인스턴스의 복사가 이뤄진다.




클래스 정의 시, clone 메소드의 호출을 허용하려면 Cloneable 인터페이스를 구현해야 한다.


Cloneable 인터페이스는 구현해야 할 추상 메소드가 없는 마커 인터페이스이다.








clone 메소드 호출의 예


class Point implements Cloneable {

private int xPos;

private int yPos;


public Point (int x, int y) {

xPos = x;

yPos = y;

}


public void showPosition() {

System.out.printf ( "[%d, %d]", xPos, yPos );

System.out.println();

}


@Override

public Object clone() throws CloneNotSupportedException {

return super.clone();                // Object 클래스의 clone 메소드 호출

}

}


접근 수준 지시자를 protected 에서 public으로 바꾸기 위한 메소드 오버라이딩

(Object는 java.lang 패지키 이므로 public으로 바꿔줘야 호출 가능하다!)


Override는 메소드를 재정의 하는 것 뿐만 아니라 접근 수준 지시자를 넓힐 수 있다. (좁힐 순 없음!!)


class InstanceCloning {

public static void main (String[] args) {

Point org = new Point(3, 5);

Point cpy;


try {

cpy = (Point) org.clone();                    // clone 메소드는 Object를 반환 하므로 Point로 꼭 형변환 해줘야함!!!

org.showPosition();

cpy.showPosition();

}

catch (CloneNotSupportedException e) {

e.printStackTrace();

}

}

}








Shallow Copy - 얕은 복사


class Rectangle implements Cloneable {


private Point upperLeft;            // 좌측 상단 좌표

private Point lowerRight;            // 우측 하단 좌표


public Rectangle (int x1, int y1, int x2, int y2) {

upperLeft = new Point (x1, y1);

lowerRight = new Point (x2, y2);

}


. . . .


@Override

public Object clone() throws CloneNotSupportedException {

return super.clone();

}


. . . .

}


class Point implements Cloneable {

private int xPos;

private int yPos;


. . . .

}


public static void main(Sring[] args) {

Rectangle org = new Rectangle(1, 1, 9, 9);

rectangle cpy;


try {

cpy = (Rectangle) org.clone();


. . . .

}

catch (CloneNotSupportedException e) {

e.printStackTrace();

}

}











Deep Copy - 깊은 복사


class Rectangle implements Cloneable {


private Point upperLeft;            // 좌측 상단 좌표

private Point lowerRight;            // 우측 하단 좌표


public Rectangle (int x1, int y1, int x2, int y2) {

upperLeft = new Point (x1, y1);

lowerRight = new Point (x2, y2);

}


. . . .


@Override

public Object clone() throws CloneNotSupportedException {

Rectangle copy = (Rectangle)super.clone();


copy.upperLeft = (Point) upperLeft.clone();

copy.lowerRight = (Point) lowerRight.clone();


return copy;

}


. . . .

}


class Point implements Cloneable {

private int xPos;

private int yPos;


. . . .

}


public static void main(Sring[] args) {

Rectangle org = new Rectangle(1, 1, 9, 9);

rectangle cpy;


try {

cpy = (Rectangle) org.clone();


. . . .

}

catch (CloneNotSupportedException e) {

e.printStackTrace();

}

}











String 인스턴스 대상 깊은 복사


class Person implements Cloneable {

private String name;                 // String 클래스는 Cloneable 구현 안함!

private int age;


. . . .

}



@Override

public Object clone() throws CloneNotSupportedException {

Person cpy = (Person) super.clone();                            // clone 메소드 호출을 통한 복사본 생성

cpy.name = new String(name);                                   // 깊은 복사의 형태로 복사본을 완성

return cpy;                                                              // 완성된 복사본의 참조 값 반환

}


String은 Cloneable 구현 안한다. 인스턴스 복사 해주려면 그냥 new String 해서 새로운 인스턴스 생성 해주면 됨.








clone 메소드의 호출과 형 변환 - 예전에는 형변환 해줘야 했음!!


class Point implements Cloneable {


. . . .


@Override

public Object clone() throws CloneNotSupportedException {


return super.clone();

}

}


Point org = new Point(1, 2);

Point cpy = (Point) org.clone();                // 형 변환해야 함!!



clone 메소드의 반환형 수정 - 형변환 안해도 됨!!!


class Point implements Cloneable {

. . . .


@Override

public Point clone() throws CloneNotSupportedException {


return (Point) (super.clone());


}

}



Point org = new Point(1, 2);

Point cpy = org.clone();                        // 형 변환 필요 없음!!!




반응형