1. 자바 코드 예시
아래의 자바 코드를 살펴봅시다.
문제가 없는 코드라고 할 수도 있겠으나, 해당 코드는 null 값이 들어왔을 경우에는 NPE가 발생합니다.
public class Lec02Main {
// str이 null일 수 있기 때문에 NPE 위험성이 존재
public boolean startsWithA(String str) {
return str.startsWith("A");
}
}
2. 자바로 문제 해결
NPE를 해결하기 위해서 자바 코드는 아래와 같이 대처할 수 있을겁니다.
- str 값이 null인 경우 exception 처리
- str 값이 null인 경우 null return
- str 값이 null인 경우 false return
다음과 같이 구현할 수 있을 것입니다.
public class Lec02Main {
// 대처1: null인 경우 exception 발생
public boolean startsWithA1(String str) {
if (str == null) {
throw new IllegalArgumentException("null이 들어왔습니다");
}
return str.startsWith("A");
}
// 대처2: null인 경우 null return
// null을 return할 수 있기 때문에 return type은 Boolean입니다.
public Boolean startsWithA2(String str) {
if (str == null) {
return null;
}
return str.startsWith("A");
}
// 대처3: null인 경우 false return
// null은 return하지 않기 때문에 return type은 boolean입니다.
public boolean startsWithA3(String str) {
if (str == null) {
return false;
}
return str.startsWith("A");
}
}
위 코드를 코틀린으로 작성해보면 어떻게 변할까요?
3. 코틀린 코드 예시
먼저 아래 코드를 살펴봅시다.
str 값의 type을 String? 으로 지정해줬기 때문에 null이 들어올 수 있다고 알려줬습니다.
그래서 str.startsWith를 사용하면 문제가 발생할 수 있다고 빨간색 밑줄로 표시해주는 것을 확인할 수 있습니다.
코틀린에서는 null 값에 대한 타입이 있기 떄문에 NPE가 발생하는 문제를 미연에 방지할 수 있다는 장점이 있습니다.
4. 코틀린을 이용한 문제 해결
자바와 동일하게 코틀린을 이용해서 문제를 해결해 보겠습니다.
대처1: null인 경우 exception을 발생시키는 부분은 파라미터 타입 설정에 null이 들어올 수 있다고 체크해주는 부분을 제외하고는 자바 코드와 별다른 점이 없습니다.
대처2: null인 경우 null을 return 해주는 경우에는 return type에도 null이 들어갈 수 있다는 것을 명시해줍니다.
대처3: null인 경우 false를 return해주는 경우는 null을 return하는 case가 없기 때문에 return type에 ?를 사용하지 않습니다.
class Lec01Main {
// 대처1: null인 경우 exception 발생
fun startsWithA1(str: String?) :Boolean {
if (str == null) {
throw IllegalArgumentException()
}
return str.startsWith("A");
}
// 대처2: null인 경우 null return
// null을 return할 수 있기 때문에 return type은 Boolean입니다.
fun startsWithA2(str: String?) :Boolean? {
if (str == null) {
return null
}
return str.startsWith("A");
}
// 대처3: null인 경우 false return
// null은 return하지 않기 때문에 return type은 boolean입니다.
fun startsWithA3(str: String?) :Boolean {
if (str == null) {
return false;
}
return str.startsWith("A");
}
}
5. null 타입만을 위한 기능
Safe call
null이 아니면 실행하고 null이면 실행하지 않는다.
fun main() {
var str: String? = "ABC"
println(str?.length)
}
Elvis 연산자
앞의 연산 결과가 null이면 뒤의 값을 사용
fun main() {
var str2: String? = "ABC"
println(str2?.length) ?: 0
}
6. Safecall과 Elvis 연산자를 이용하여 코드 개선
변경 전 코드와, 변경 후 코드를 같이 작성하였습니다.
Safe call과 Elvis 연산자를 사용하니 코드가 간결해진 것을 확인할 수 있습니다.
// 대처1: null인 경우 exception 발생
fun startsWithA1(str: String?) :Boolean {
if (str == null) {
throw IllegalArgumentException()
}
return str.startsWith("A");
}
fun startsWithB1(str: String?): Boolean {
return str?.startsWith("A")
?: throw IllegalArgumentException()
}
// 대처2: null인 경우 null return
// null을 return할 수 있기 때문에 return type은 Boolean입니다.
fun startsWithA2(str: String?) :Boolean? {
if (str == null) {
return null
}
return str.startsWith("A");
}
// str이 null이라면 null이 그대로 반환됨
fun startsWithB2(str: String?) :Boolean? {
return str?.startsWith("A")
}
// 대처3 null인 경우 false return
// null은 return하지 않기 때문에 return type은 boolean입니다.
fun startsWithA3(str: String?) :Boolean {
if (str == null) {
return false;
}
return str.startsWith("A");
}
// str이 null이라면 null이 그대로 반환됨
fun startsWithB3(str: String?) :Boolean? {
return str?.startsWith("A") ?: false
}
7. null 아님 단언 (!!)
특이하게도 타입은 null일 수 있다고 선언하였지만, 확실하게 null이 아니라고 판단 될 경우에 사용할 수 있는 문법이 있습니다. "!!" 를 사용하게 되면 이 변수는 null이 정말 아니야! 라고 선언하는 것과 동일하다고 보면 됩니다.
fun startsWithC(str: String?) {
str!!.startsWith("A")
}
8. 자바 프로젝트에서의 코틀린
자바 프로젝트에서 코틀린을 사용하는 경우가 있습니다.
이러한 경우 null은 어떻게 처리되는지를 확인해 봅시다.
코틀린은 null과 관련된 annotation을 이해합니다.
null과 관련된 annotation 패키지는 다음과 같은 것들이 있습니다.
- javax.annotation 패키지
- android.support.annotation 패키지
- org.jetbrains.annotation 패키지
코드를 통한 예시를 살펴보겠습니다.
1. @Nullable에 대한 처리
public class Person {
private final String name;
public Person(String name) {
this.name = name;
}
@Nullable
public String getName() {
return name;
}
}
person.name은 null 일 수 있습니다.
startsWithC 라는 메서드는 null이 들어올 수 없기 떄문에 아래와 같이 에러가 발생하는 것을 확인할 수 있습니다.
2. @NotNull
@NotNull이라는 annotation을 사용하게 되면 name이라는 값은 null일 수가 없기 때문에 아래와 같이 발생하던 문제가 사라진 것을 확인할 수 있습니다.
3. annotation이 없는 경우 (플랫폼 타입)
annotation이 없는 경우 null인지 아닌지를 판단할 수 없는 상태이고 이를 플랫폼 타입이라고 합니다.
이럴때는 기존 자바코드와 동일하게 런타임 시점에 NPE가 발생하는 것은 동일합니다.
public class Person {
private final String name;
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
아래 코드를 실행하면 NPE가 발생하는 것을 확인할 수 있습니다.
fun main() {
val person : Person = Person(null)
startsWithC(person.name);
}
fun startsWithC(str: String) {
str.startsWith("A")
}
코틀린에서 자바코드를 사용할 떄는 null을 꼼꼼하게 처리가 필요
라이브러리를 사용하게 되면, wrapping 해서 처리가 가능.
'공부방 > Kotlin' 카테고리의 다른 글
코틀린에서 반복문을 다르는 방법 (0) | 2023.05.17 |
---|---|
코틀린에서 조건문을(제어문) 다루는 방법 (0) | 2023.05.17 |
코틀린에서 연산자를 다루는 방법 (0) | 2023.05.17 |
3. 코틀린에서 Type을 다루는 방법 (0) | 2023.05.16 |
1. 코틀린에서 변수를 다루는 방법 (0) | 2023.05.16 |