public boolean startsWithA(String str) {
return str.startsWith("A");
}
위의 코드는 null 값을 갖고오면 NPE가 나기 때문에 안전한 코드가 아니다.
따라서 자바에서 null을 체크하는 안전한 코드로 고치는 방법은,
public boolean startsWithA1(String str) {
if(str == null) {
throw new IllegalArgumentsException("null이 들어왔습니다.");
}
return str.startsWith("A");
}
=> 위와 같이 str이 null일 경우 Exception을 내거나,
public Boolean startsWithA2(String str) {
if(str == null) {
return null;
}
return str.startsWith("A");
}
=> 위와 같이 str이 null일 경우 null을 반환하거나, (null 값을 반환해주므로 메소드 타입은 null 값 반환 가능한 Boolean)
public boolean startsWithA3(String str) {
if(str == null) {
return false;
}
return str.startsWith("A");
}
=> 위와 같이 str이 null일 경우 false를 반환한다.
fun startsWithA1(str: String?): Boolean {
if(str == null) {
throw IllegalArgumentException("null이 들어왔습니다.")
}
return str.startsWith("A")
}
=> 들어오는 값(파라미터, str)이 null 일 수 있으므로, 타입 지정 후 오른쪽에 “?(물음표)”를 붙여주고, 함수 값 반환 시 Boolean 타입으로 표시를 해주므로(단, null 값을 반환할 수는 없음), 함수의 타입(Boolean)을 맨 오른쪽에 표시해준다.
fun startsWithA2(str: String?): Boolean? {
if(str == null) {
return null
}
return str.startsWith("A")
}
=> 들어오는 값(파라미터, str)이 null 이라면 null 값을 반환하므로, 파라미터 타입 뿐만 아니라, 함수의 타입(Boolean) 오른쪽에도 “?(물음표)”를 표시해준다.
fun startsWithA3(str: String?): Boolean {
if (str == null) {
return false
}
return str.startsWith("A")
}
=> Kotlin은 null 일 수 있는 변수에 대해서 바로 메소드콜을 할 수 없는데, 문맥상 위에서 null 체크를 해주면 자동으로 아래에 있는 변수는 null이 아닐거라고 컴파일러가 자동으로 추측을 해준다.
따라서, 아래에 있는 str 변수는 null 값이 아니라는 의미로 초록색으로 표시되게 된다.
번외로,
fun startsWithA(str: String?): Boolean {
return str.startsWith("A")
}
=> 맨 위의 NPE 위험이 있는 JAVA 코드처럼 Kotlin에서도 null에 대한 체크 없이 바로 파라미터 값을 반환하려고 하면, str 값이 null 일수도 있기 때문에 바로 에러가 난다.
fun startsWithA(str: String): Boolean {
return str.startsWith("A")
}
=> 위의 코드의 경우, 파라미터 타입 뒤에 “?(물음표)” 가 없으므로, null 값일 때 파라미터 값으로 받아올 수 없는 것으로 간주하고, str.startsWith(“A”)가 바로 호출된다.
Kotlin에서는 null이 가능한 타입을 완전히 다르게 취급한다.
=> null이 가능한 타입만을 위한 기능은 없을까?!
==> 있다!!!
val str: String? = "ABC"
str.length // 불가능
srt?.length // 가능!!
null이 아니면 실행하고, null이면 실행하지 않는다. (그대로 null)
val str: String? = "ABC" //null이 아니라면 그 값이 호출
str?.length ?: 0 // null인 경우 0 호출
앞의 연산 결과가 null이면 뒤의 값을 사용
Elvis 연산은 early return 에도 사용할 수 있다.
< JAVA.ver >
public long calculate(Long number) {
if (number == null) {
return 0;
}
//다음 로직
}
↓
< Kotlin.ver >
fun calculate(number: Long?): Long {
number ?: return 0
//다음 로직
}
nullable type 이지만, 아무리 생각해도 null이 될 수 없는 경우
fun startsWithA1(str: String?): Boolean {
return str!!.startsWith("A")
}
=> 변수!!.startsWith(“값”) → 절대 null 이 아니야!! 라는 뜻
Kotlin에서 Java 코드를 가져다 사용할 때 어떻게 처리될까?!
<Person.java>
import org.jetbrains.annotation.Nullable;
public class Person {
private final String name;
public Person(String name) {
this.name = name;
}
@Nullable
public String getName() {
return name;
}
}
<Lec02Main.kt>
package com.lannstark.lec02
fun main() {
val person = Person("공부하는 개발자") //Person.java를 불러옴
startsWithA(person.name) //null 을 쓸 수 없으므로 빨간 밑줄이 쳐진다.
//사용하고 싶다면 java 코드에서 @Nullable => @NotNull로 바꾸거나, startsWithA 함수의 파라미터의 타입 뒤에 "?" 를 붙여준다.
}
fun startsWithA(str: String): Boolean {
return str.startsWith("A")
}