TiL 230614

전선웅·2023년 6월 14일
1

TIL

목록 보기
6/12

무엇을 배웠나

-중첩 선언과 객체
-예외 처리

확장학습

객체와 변수할당

중첩 인터페이스 연습을 하던 중, 분명히 setter의 매개변수에 'ClickListener clickListener'을 명시돼있는데, 'new ClickListener()'로 변수할당 없이 객체만 만들어 넣는 것에 의문이 생겼다.

public class Button {
    //정적 멤버 인터페이스
    public static interface ClickListener {
        void onClick();
    }

    //필드 : 클릭 이벤트 발생 시 어떤 동작을 수행해야할 지 결정
    private ClickListener clickListener;

    //메서드
    public void setClickListener(ClickListener clickListener) {
        this.clickListener = clickListener;
    }
    public void click() {
        this.clickListener.onClick();
    }
}

public class ButtonExample {
    public static void main(String[] args) {
        //Ok 버튼
        Button buttonOk = new Button();
        class Oklistener implements Button.ClickListener {
            @Override
            public void onClick() {
                System.out.println("Ok 버튼 클릭");
            }
        }
        buttonOk.setClickListener(new Oklistener()); //문제 부분1
        buttonOk.click();

        //Cancel 버튼
        Button buttonCancel = new Button();
        class CancelListener implements  Button.ClickListener {
            @Override
            public void onClick() {
                System.out.println("Cancel 버튼 클릭");
            }
        }
        buttonCancel.setClickListener(new CancelListener());//문제 부분2
        buttonCancel.click();

    }
}

찾아보니 이는 일회성으로 객체가 사용될 때, 효율성을 위해 굳이 변수를 할당하지 않는 방법이다.
객체를 만들어 바로 메서드에 전달하고, 메서드가 종료되면 객체를 참조하는 것이 없으므로 가비지 컬렉터에 의해 그 객체는 메모리에서 제거된다.

추론해보면, 변수가 할당되지 않은 객체는 일단은 메모리에서 버려지기 전, 생성시점에 메모리에 로드되었다는 것인데, "변수없이 메모리에 로드될 수 있나?"는 물음이 생긴다. 답은 '로드될 수 있다.'이다. 하지만 주소를 가리키는 변수가 없기에, 재사용은 불가능하다. 그래서 일회성이라는 것이다.

비슷한 방식으로 익명 객체를 사용하면 다음과 같이 코드를 더 쉽고 간단하게 바꿀 수 있다.

public class ButtonExample {
    public static void main(String[] args) {
        //Ok 버튼
        Button buttonOk = new Button();
        buttonOk.setClickListener(new Button.ClickListener() {
            @Override
            public void onClick() {
                System.out.println("Ok 버튼 클릭");
            }
        });
        buttonOk.click();

        //Cancel 버튼
        Button buttonCancel = new Button();
        buttonCancel.setClickListener(new Button.ClickListener() {
            @Override
            public void onClick() {
                System.out.println("Cancel 버튼 클릭");
            }
        });
        buttonCancel.click();

    }
}

사용자 정의 예외 클래스의 super(message)와 실제 예외 처리 단계에서 getMessage()의 관계

public class myException extends Exception {
	public myException() {}
    public myException(String message) {
    	super(message);
    }
}

public class Login {
	public static void main(String[] args) {
    	try {
        	login("선웅","1234");
        } catch (Exception e) {
        	System.out.println(e.getMessage);
        }
    }
}

public static void login(String id, String password) extends Exception {
	if (!id.eqauls("선웅")) {
    	throw new myException("아이디가 올바르지 않습니다.");
    } 
    
    if (!password.equals("1234")) {
    	throw new myEsception("패스워드가 올바르지 않습니다.");
    }

}

super(message)를 사용해 부모 클래스에 메시지를 저장하는 이유는 상속과 다형성의 원리에 기반한다.

자바에서는 예외와 오류를 모두 Throwable 클래스로부터 상속받은 클래스를 사용하여 표현한다. Throwable 클래스 자체는 모든 "던질 수 있는"(throwable) 상황을 대표하는 최상위 클래스이다. 이 클래스는 두 가지 하위 클래스, Exception 클래스와 Error 클래스로 나뉜다.

Exception 클래스는 개발자가 처리할 수 있는 예외 상황을 나타내는 클래스로서, 이 클래스를 상속받은 예외는 대부분의 경우 프로그래머가 예측하고 처리할 수 있는 상황에 대한 것이다. 이로 인해 개발자가 애플리케이션의 논리적 오류를 잡아내고 그에 따른 적절한 조치를 취할 수 있다. 그렇기 때문에 사용자 정의 예외 클래스는 대부분 Exception 클래스를 상속받아 작성된다.

Exception 클래스는 내부에 detailMessage라는 필드를 가지고 있다. 피상속자인 myException은 'super(message)'라는 상속자의 생성자를 이용해 메시지를 저장할 수 있는 detailMessage 필드를 가져와 예외 객체를 생성한다. 이후 detailMessage필드는 getMessage() 메소드를 통해 접근할 수 있다. 이런 방식으로 예외 메시지를 저장하고 필요할 때 접근해서 사용한다.

사용자 정의 예외 클래스에서 메시지를 저장하는 이유는 추후에 발생한 예외에 대한 상세한 정보를 확인하기 위함이다. 예외가 발생했을 때 단순히 예외의 타입만 알고 있으면 그 원인을 파악하기 어렵다. 예외가 발생한 이유를 사후에 상세히 알 수 있도록, 메시지를 사전에 작성하고 이를 함께 저장해 놓는다. 사용자 또는 개발자는 어떤 예외가 발생했는지 파악하고 적절한 조취를 취할 수 있다.

profile
꿈 많고, 꿈 크고, 꿈 좋은

0개의 댓글