포스트

(Day 31) 중첩클래스 및 실습

복습

예외처리

예외처리의 고전적 방법

예외를 처리하기 위한 방법은 어떻게 발전해왔나? 호출된 메서드에서, 호출한 메서드에게 정보를 전달하는 방식으로 생각하기 쉬운 것은 return value를 이용하는 것이다.

ArrayList 클래스의 indexOf() 메서드가 그러한 방법을 사용한다. 원하는 값이 없는 경우 (예외가 발생한 경우) 인덱스의 값으로 쓸 수 없는 음수값, 그 중에서 대표적인 -1이라는 값을 리턴하여 알려준다.

그런데 이렇게 리턴값을 이용하여 예외발생 여부를 알려주는 것은 한계가 생긴다. 정상적인(유효한) 경우에서 모든 리턴값을 사용하는 경우 (예를 들면 get() 과 같이 ArrayList에서 특정 인덱스에 있는 값을 가져오는 경우) 특정 리턴값을 사용할 수 없다.

그래서 return value가 아닌 다른 채널을 통해서 예외 여부를 알려주게 됐다. 힙 영역에 생성한 인스턴스를 이용할 수 있는데, 이것이 문법으로 발전하여 Throwable 클래스와 throw, throws 명령어가 고안되었다. 그리고 어떤 코드들에 대하여 예외처리를 실행할지 try ~ catch ~ finally 코드블럭을 지정하는 문법이 발생했다.

처리할 수 없는 Error, 처리할 수 있는 Exception으로 Throwable의 서브클래스들이 고안되었고, 이후 매번 throws 키워드로 메서드의 예외를 던짐을 선언해주기 불편하다 보니 RuntimeException이라는 서브클래스는 별도로 throws 선언을 해주지 않아도 컴파일러에서 자동으로 던져주는 것으로 처리하게 되었다. (그래서 RuntimeException은 신경쓰지 않으면 나도 모르게 암시적으로 JVM에게까지 예외가 갈 수 있다. 컴파일러가 봐준다고 무조건 좋은 게 아니다.)

finally 예외 발생 여부에 무관하게 무조건 실행해야 하는 블럭을 설정해둔 것이다. 왜 이런 기능이 필요했을까? 자원 해제를 위해서다. 입출력장치나 메모리 등 자원을 가지고 있는 상태에서 예외로 해제하지 않는 문제를 막기 위해서다. 그 외의 목적이라도 반드시 실행되어야 하는 코드가 있다면 finally 블럭을 만들어 사용할 수 있다.

finally 블럭이 사용되는 패턴이 아주 일정하다보니 try ( ) { } 형태로 사용하는 try-with-resources 문법이 등장한다. finally 블럭을 따로 잡지 않아도 소괄호에서 선언된 자원들은 try 블럭이 끝나면 예외발생여부와 무관하게 자원을 해제(close())하게 된다. (AutoCloseable 클래스의 서브클래스들만 가능)

메서드가 던진 예외는 어떻게 받나요?

catch 블럭으로 받는다. 없으면 상위 호출자(Caller)에게 그 예외를 던진다. 말 그대로 throws.

자료구조 : Linked List

Linked List 클래스 구현하기

Linked List 기능 구현

-> Inkodo로 시각화용 필기 및 코드 구현함

중첩 클래스(Nested Class)

디렉토리에 .java 파일을 만들어서 같은 이름의 클래스를 만들면, 그것은 패키지 멤버 클래스이다. 대부분의 클래스는 이렇게 작성된다. 그런데 단 하나의 클래스에서만 사용하는 클래스 라면 중첩 클래스 문법을 사용할 수 있다.

중첩 클래스는 클래스 안에 클래스를 선언한 것이다. 왜 이런 짓(?)을 하는가? 단 하나의 클래스에서만 사용할 클래스로 설계했고, 패키지 안에 클래스를 추가하지 않기 때문에 유지보수가 쉬워지기 때문이다.

자바는 클래스 로더를 통해 필요시에만 .class 파일 (바이트코드) 를 메모리에 올린다. 하나의 .java파일에 여러 개의 클래스가 있다면, 컴파일하면 클래스 개수만큼의 .class 파일이 생성된다. 중첩클래스도 마찬가지이다. 소스파일의 개수와 무관하게 그 안의 클래스 블럭마다 .class 파일이 만들어진다. 당연히 중첩클래스도 예외가 아니다. 다만 중첩클래스를 포함하는 상위 클래스에 소속되어 있는 것으로 나온다. (파일명에 $ 써서 포함 표현)

소프트웨어의 깨달음

건축과 소프트웨어 개발의 공통점은 설계하고 만든다는 건데, 가장 큰 차이점은, 건축은 설계도대로 만들어야 하는데, 소프트웨어는 설계도의 변경이 건축보다 아주아주 많이 많이 일어난다. 건축도 설계변경이 있긴 하지만 소프트웨어는 훨씬 더 많은 설계변경이 있다.

설계도대로 만들어주는게 중요한 게 아니라 사용자에게 가치있는 소프트웨어를 만드는 것이 중요하다는 깨달음이 퍼졌다. 그래서 사용자에게 바로바로 피드백을 받고 기민하게(애자일하게) 개발하자는 쪽으로 트렌드가 바뀌었다. 그 다음에 참여인원에 따라 스크럼이라는 방법이 등장한다. 시대가 그런시대이다. 지금 시대의 개발자들은 짧게 개발하고 기능 테스트를 하는 것이 중요하다. 단위테스트도 한다. 단위테스트를 해야, 적어도 자기가 짠 코드를 테스트를 할 수 있는 것은 개발자에게 아주아주 중요한 역량이다.

적용한 기술

링크드 리스트를 직접 만들었다. 링크드 리스트를 컴포지트 패턴을 통해 구현한 메뉴에 적용하였음 왜? 배열로 동작하는 경우 배열의 크기를 초과하여 메뉴를 add하는 경우에 새로 배열을 만들고 복사하는 일이 있었기 때문에. (물론 실무에서는 조회 속도가 O(1)인 어레이리스트를 쓰는 것이 나을 것이다) 혹은 삽입이나 삭제도 어려운 점이 있었다.

일반화 재적용하기

ArrayList, LinkedList .. 메서드가 통일되어있다. 그래서 인터페이스로 뽑아내서, 리스트를 사용하는 클래스에서 해당 인터페이스를 사용한다고 선언하여 다형적 변수를 적용하면 유지보수가 편해진다!!

AI의 시대

코어 기술을 가진 사람이 살아남을 것이다. 코어 기술이 뭔가? 기본 문법, 디자인패턴, 리팩터링과 같은 기술이다. 응용이 아니다. Vue.js, React 써봤다가 아니다.

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.