본문 바로가기

프로그래밍 언어/코틀린_Kotlin_더파기

Kotlin더파기_06_Null & Exception_널과 예외

# Null 널

 

null은 값이 없다는 것을 나타낸다.

코틀린에서는 null로 지정할 수 있는 것과

지정할 수 없는 것이 있다.

 

null값을 가질 수 있는 것을 nullable (널러블)

가질 수 없는 것을 non-nullable (난널러블)이라고 한다.

 

많은 프로그래밍 언어는 어떤 타입의 변수도 null값을 가질 수 있다.

또한 기본값이 없는 변수의 초기값으로 자주 null을 사용한다.

그래서 NullPointerException(널 포인터 예외)라는 에러가 자주 발생한다.

 

코틀린은 이런 에러를 방지하기 위해 null을 지정(명시)하는 것만 null값을 가질 수 있다.

 

위 코드에서 변수 fruit(과일)을 정의한 후 String(문자열) 값으로 apple을 설정했다.

그리고 fruit에 null값을 넣으면 빨간줄로 경고를 나타낸다.

"Null은 non-null타입인 String의 값이 될 수 없다 "

 

 

null 안전 처리법

변수 fruit에 내부함수인 readLine()함수를 넣어보자.

readLine() 함수는 콘솔에서 입력한 값을 출력해 주는 내부함수이다.

실행한 후 콘솔창에 글자를 입력하면 아래에 출력한다.

 

String?

위 코드는 '문자열 또는 nullable'라는 뜻이다.

즉 문자열 또는 문자열 값이 없는것도 가능하다는 뜻이다.

 

마우스 포인터를 readLine()에 가져가 보면 이 함수의 반환 타입이 String? 임을 알 수 있다.

즉 null값도 가능하다.

그러므로 아래와 같이 변수값에 null값을 입력해도 에러가 나지 않는다.

 

이번에는 capitalize() 함수를 호출해보자.

capitalize()는 문자열의 첫글자를 대문자로 바꿔주는 내부함수다.

 

capitalize함수의 호출점에 빨간줄 경고가 뜬다.

"null호출 가능한 String?은 safe 또는 non-null asserted 호출만 할 수 있다."

 

readLine()함수가 null값을 반환할 수 있으므로 그런 경우를 대비해서 (?.) 안전모드 또는 (!!.) null아님 단정모드를 사용하라는 말이다.

 

null 안전처리 방법

 

  • ?.
  • !!.

1. safe call operator(안전 호출 연산자) ?.

 

safe call operator(안전 호출 연산자)를 사용한다.

위와 같이 안전호출 연산자를 사용하면 null이 아닐때만 capitalize함수를 호출하고 만약 null이면 건너뛰어 그 다음 코드를 실행한다.

 

실행 후 apple을 입력하면 null이 아니므로 첫글자를 대문자로 바꿔 출력해준다.

만약 null일때와 아닐때 어떻게 하라는 명령을 내리고 싶으면 let (~하게 하다)을 사용하여 표현할 수 있다.

 

위 코드는 만약 비어있지 않으면 capitalize()함수를 호출하고

그렇지 않으면(비어있다면) 문자열 "Blank!"를 출력하라는 뜻이다.

it은 반환받는 값의 참조를 나타내는 문자다.

 

2. non-null assertion operator (null 아님 단정 연산자) !!.

 

이 연산자는 double-bang이라고도 한다.

아래와 같이 !!. 단정 연산자는 컴파일러가 null발생을 미리 알 수 없는 상황에 사용할 수 있다.

예를 들면 다음과 같은 경우에 사용할 수 있다.

 

  • null가능 타입의 변수값을 어떤 함수에서 확인한 후 다른 함수에서 그 값을 받아서 사용할 때
  • 시스템 라이브러리의 변수를 참조하거나 함수를 호출할 때
  • 언제 발생할 지 모르는 에러를 파악하고 싶을 때

 

 

3. 값이 null인지 if로 검사

 

아래와 같은 조건문을 만들 수 있다.

 

if 조건에서 (fruit가 null이 아니라면) 으로 검사하는 방법은 null일 때 실행해야 하는 코드가 복잡한 경우에 적합하다.

그 외의 경우는 안전호출(?.) 연산자를 사용하는 것이 더 좋다.

그 이유는 코드가 간결하고 연속해서 사용할 수 있는 유연성도 있기 때문이다.

 

4. null 복합연산자 ?:

 

엘비스 연산자라고도 한다.

연산자를 오른쪽으로 회전하면 엘비스 프레슬리의 헤어스타일과 닮았다나 뭐라나...

 

엘비스 연산자(?:)는 이 연산자를 기준으로 왼쪽(fruit?.length) 값이 null이 아니면 이 값을 fruitReceived에 저장하고 null이면 기본값 "apple"이 저장된다.

이렇게 함으로써 fruitReveived의 값은 null이 아닌 값이 정해진다.

 

또한 엘비스 연산자를 사용하면 let함수에 사용한 if조건문 대신 사용할 수 있다.

위의 코드를 다음과 같이 바꿀 수 있다.

 

 

# exception (예외)

 

예외는 프로그램에 어떤 에러가 생겼다는 것을 나타내기 위한 도구다.

 

먼저 null을 출력하는 코드를 만들어 본다.

 

2번줄: 토마토 요리에 필요한 토마토 개수를 나타내는 변수를 만들고 null값을 넣는다.

3번줄: 요리 준비가 된 상태를 확인하는 변수를 만들고 셔플랜덤의 마지막 수가 3이면 변수에 저장한다.

4번줄: 만약 요리 준비가 된 상태면 토마토 개수에 2를 넣는다

7번줄: "토마토 ~개로 요리"를 출력한다.

 

위 코드에서 셔플랜덤수가 3이 아니면 "토마토 null개로 요리"가 출력될 것이다.

 

만약 위 코드에 다음과 같은 코드를 추가하면 Exception에러가 난다.

 

 

null이 아니라고 단정한 키워드(!!)를 사용했는데 랜덤수가 3이 아닌 경우에는 null이 되므로 예외가 발생한다.

plus()함수는 연산자+를 대신할 수 있는 함수다.

이외에도 빼기는 minus() , 곱하기는 times(), 나누기(divide)는 div(), 나머지(remain)는 rem() 등이 있다.

 

예외로 인해 프로그램이 종료되는 것을 crash(크래쉬; 충돌, 실패)라고 한다.

코틀린에서는 변수의 기본 타입을 null 불가능으로 정해두었다.

 

 Throw IllegalStateException

 

thorw 키워드는 예외가 발생하면 그것을 던져준다(throw).

이때 사용할 수 있는 함수가 IllegalStateException()이다.

불법 상태 예외라는 뜻이다.

함수의 인자로 문자열을 출력할 수 있으므로 문제점을 파악할 수 있다.

 

throw IllegalStateException() 처럼 사용해서 예외가 생기면 알려준다.

이것을 사용해서 예외상태를 체크할 수 있는 throwCheck() 함수를 만들어 보자.

 

엘비스 연산자를 사용하여 tomatoCooking값에 2가 들어 있으면 다음 줄로 넘기고 false이면 오른쪽 throw ~를 실행하고 "요리못함"이라는 문자열을 출력한다.

에러는 아래 처럼 나타난다.

 

 

예외 클래스 만들기

 

예외를 class로 만들면 상속해서 프로젝트 전체에서 재사용할 수 있다.

또한 예외 발생했을 때 실행할 코드를 추가할 수 있는 장점이 있다.

 

 

예외 처리(try-catch)

 

예외가 일어날 가능성이 있는 코드 주위에 try-catch문을 만들어 대비할 수 있다.

코드를 한번 시도(try)해 보고 잡아내라(catch)는 뜻이다. 

아래처럼 사용할 수 있다.

 

try-catch에서는 예외가 발생할 때만 catch문을 실행한다.

이렇게 사용하면 try문에서 null이 발생해도 catch문에서 예외로 처리하기 때문에 종료되지 않고 다음 코드를 계속 실행할 수 있다. 

 

checkNotNull함수

 

앞에서 만든 클래스 예외보다 좀 더 쉬운 방법은 checkNotNull이라는 내부함수를 사용하는 것이다.

 

 

이 내부함수는 null이면 IllegalStateException을 알려준다.

2개의 인자를 받으며 첫번째는 null검사할 값, 두번째는 콘솔에 출력할 에러메시지다.

 

표준라이브러리에는 이렇게 검사와 에러에 사용할 수 있는 내부함수들이 있다.

이런 함수들을 precondition function이라고 한다.

이 함수들은 코드가 실행되지 전에 만족해야 하는 전제조건을 정의할 수 있다.

 

  • checkNotNull()
  • require()
  • requireNotNull()
  • error()
  • assert()

 

결론

 

다른 언어에서는 null 발생이 빈번하다.

그래서 신생 언어인 코틀린은 에러에 좀 더 민감하게 만들어져 있다.

 

null에러가 나지 않게 하려면 초기값 설정에 신경을 쓰고

만일의 에러에 대비하여 다양한 null 처리법으로 대처한다.