| final, finally, finalize 차이점

 

1. final

 

final은 사용되는 문맥에 따라 다르다.

변수에 적용하면 : 해당 변수의 값은 변경이 불가능해진다. 상수가 되기 때문

변수의 참조에 적용하면 : 참조 변수가 힙 내의 다른 객체를 가리키도록 변경할 수 없다.

 

메서드에 적용하면 : 해당 메서드를 상속받는 하위 클래스에서 오버라이딩 할 수 없다.(상속받는 하위 클래스에서도 변경이 되지 않아야 하는 메서드의 경우 final을 붙이면 된다.)

 

클래스에 적용하면 : 해당 클래스를 다른 클래스가 상속받을 수 없다. 즉, final 클래스의 하위 클래스를 정의할 수 없다. ->이건 언제 쓰는 걸까??

 

 

 

2. finally

 

finally는 try-catch 블록 뒤에 둘 수 있는 선택적인 블록인데 try-catch문이 끝나기전에 항상 꼭 실행되어야하는 로직이 있을 경우 finally절에 두면된다.

try-catch블록과 함께 사용되며 예외가 던져지더라도 항상 실행될 코드를 지정하기 위해 사용된다. finally블록은 try와 catch블록이 전부!!! 실행된 후, 그리고 제어 흐름이 원래 지점으로 돌아가기 전에 실행된다.(코드 확인할 것)

 즉, 보통 뒷 마무리 코드를 작성하는데 사용된다.

(DB연결을 하거나 I/O 스트림을 열었을때 다 사용하거나면 닫아주는 작업 등)

public class TryEx {

    public static String lem(){
        System.out.println("lem");
        return "return from lem";
    }// lem()
     
    public static String foo(){
        int x = 0; 
        int y = 5;
         
        try{
            System.out.println("start try");
            int b = y/x;
            System.out.println("end try");
            return "returned from try";
        }catch(Exception e) {
            System.out.println("catch");
            // catch문 실행 된 후(return문 까지 실행 된 후) finally문 실행된 후 마지막 catch문의 return 값이 반환된다.
            return lem() + " | returned from catch";
        }finally{
            System.out.println("finally");
        }
    }// foo()
     
    public static void bar(){
        System.out.println("start bar");
        String v = foo();
         
        System.out.println(v);
        System.out.println("end bar");

    }// bar()
     
    public static void main(String[] args){
        bar();
    }// main()
     
}// class
/*
 *      try 블럭을 실행하다가 예외를 만나면 catch 블럭으로 간 후, catch블럭이 실행된다. 이때 catch블럭의 return문까지 모두 다 실행 된 후, 
 *      finally블럭이 실행 된 다음에서야 return이 이루어지는 것을 확인할 수 있다.
 *      즉, finally 블럭은 try 블럭이 종료되는 순간 실행된다. 만약 try블럭 안에 return문을 넣더라도 finally블록은 try 블록이 종료되는
 *      순간 실행된다. try블럭에서 return | continue | break 문을 실행하거나 예외를 던진다거나해도 실행되는 것이다.
 * 
 *      단,  try/catch 블록 수행 중에 가상머신이 종료되거나
 *          try/catch를 수행하고 있던 쓰레드가 죽어버리면 finally블럭이 실행되지 않는다.
 * */

 

 

 
<결과>
start bar
start try
catch
lem
finally
return from lem | returned from catch
end bar
 
=>    즉, 코드 수행 순서가
  try문 실행-> 예외 발생 -> catch문 실행( return문에 있는 코드 까지 모두 실행) -> finally문 실행 -> return 수행
 
 
 

Q) Java의 finally 블록은 try-catch-finally의 try블록 안에 return 문을 넣어도 실행되나?

A) try 블럭을 실행하다가 예외를 만나면 catch 블럭으로 간 후, catch블럭이 실행된다. 이때 catch블럭의 return문까지 모두 다 실행 된 후, finally블럭이 실행 된 다음에서야 return이 이루어지는 것을 확인할 수 있다.

즉, finally 블럭은 try 블럭이 종료되는 순간 실행된다. 만약 try블럭 안에 return문을 넣더라도 finally블록은 try 블록이 종료되는 순간 실행된다. try블럭에서 return | continue | break 문을 실행하거나 예외를 던진다거나해도 실행되는 것이다.

 

단, try/catch 블록 수행 중에 가상머신이 종료되거나

 

  try/catch를 수행하고 있던 쓰레드가 죽어버리면 finally블럭이 실행되지 않는다.

 

 
 
3. finalize()
 
finalize() 메서드는 java garbage collector가 더 이상의 참조가 존재하지 않는 객체를 발견한 순간 호출하는 메서드다. 즉 더이상 사용되지 않는 객체가 있을때 메모리 낭비를 막기 위해서 garbage collector가 이 객체를 없애버리는데 이때 해당객체의 finallize 메서드를 호출해서 없앤다. 이 finallize()는 java.lang.Object클래스로 부터 상속받아 모든 클래스의 객체가 가지고 있는 메서드다. 즉, 만약 객체가 삭제되기 직전에 실행되어야 하는 로직같은게 있으면 Object 클래스에 정의된 finalize() 메서드를 오버라이딩하여 정의할 수 있다. 
 
하지만!! finalize()는 언제 호출될지 알 수 없기 때문에, finalize()를 오버라이딩 했다고해서 여기에 의존하는 방식의 코딩은 좋은 방법은 아닐 수 있다.

 

+ Recent posts