?
fun strLenSafe(s: String?): Int =
s?.length ?: 0
fun main(args: Array<String>) {
val x: String? = null
println(strLenSafe(x)) // 0
println(strLenSafe("abc")) // 3
}
?.
s?.method()
if (s != null) s.method() else null
fun printAllCaps(s: String?) {
val allCaps = if (s != null) s.toUpperCase() else null
val allCaps: String? = s?.toUpperCase()
println(allCaps)
}
fun printAllCaps(s: String?) {
val allCaps: String? = s?.toUpperCase()
println(allCaps)
}
?:
return
이나 throw
구문 또한 expression이므로, 엘비스 연산자에 사용가능하다.fun strLenSafe(s: String?): Int = s?.length ?: 0
class Address(val streetAddress: String, val zipCode: Int,
val city: String, val country: String)
class Company(val name: String, val address: Address?)
class Person(val name: String, val company: Company?)
fun printShippingLabel(person: Person) {
val address = person.company?.address
?: throw IllegalArgumentException("No address")
with (address) {
println(streetAddress)
println("$zipCode $city, $country")
}
}
as?
foo as? String
if (foo is String) foo as String else null
?:
엘비스 연산자와 함께 많이 사용class Person(val firstName: String, val lastName: String) {
override fun equals(o: Any?): Boolean {
val otherPerson = o as? Person ?: return false
return otherPerson.firstName == firstName &&
otherPerson.lastName == lastName
}
}
fun main(args: Array<String>) {
val p1 = Person("Dmitry", "Jemerov")
val p2 = Person("Dmitry", "Jemerov")
println(p1 == p2) // true
println(p1.equals(42)) // false
}
as
is
를 통해 미리 변환 가능한 타입인지 확인 해야한다.as
로 지정한 타입이 변환 불가능하다면, ClassCastException
이 발생!!
foo!!
if (foo != null) foo else throw NullPointerException()
NOTE:
실제 널에 대해!!
를 사용하면NullPointerException
이 발생한다.
!!
를 한줄에 여러번 쓰는 건 피해야 한다.
person.company!!.address!!.country
코드 몇번째 라인에서 발생했는지는 알 수 있으나, 자세히 어떤 값에서 발생했는지는 알 수 없다.
let
함수if (email != null) sendEmailTo(email)
email?.let { sendEmailTo(it) }
val person: Person? = getTheBestPersonInTheWorld()
if (person != null) {
sendEamilTo(person.email)
}
getTheBestPersonInTheWorld()?.let { sendEmailTo(it.email) }
lateinit var
var
여야 한다.lateinit property XXXX has not been initialized
라는 예외가 발생한다.class MyService {
fun performAction(): String = "foo"
}
class MyTest {
private lateinit var myService: MyService
@Before fun setUp() {
myService = MyService()
}
@Test fun testAction() {
Assert.assertEquals("foo",
myService.performAction())
}
}
fun String?.isNullorBlank(): Boolean =
this == null || this.isBlank()
fun main() {
println("".isNullOrBlank()) // true
println(null.isNullOrBlank()) // true
}
isNullOrBlank()
를 제공한다.fun <T> printHashCode(t: T) {
println(t?.hashCode())
}
fun main(args: Array<String>) {
printHashCode(null)
}
T
를 Any?
타입으로 추론한다.fun <T: Any> printHashCode(t: T) {
println(t.hashCode())
}
fun main(args: Array<String>) {
printHashCode(null) // Compile Erorr
}
// Type parameter bound for T is not satisfied: inferred type Nothing? is not a subtype of Any
@NotNull
, @Nullable
과 같이 널 가능성 애노테이션이 없을 경우, 코틀린 컴파일러는 플랫폼 타입으로 인식한다.Java | Kotlin |
---|---|
@Nullable MyClass | MyClass? |
@NotNull MyClass | MyClass |
MyClass | MyClass? or MyClass |
?.
, ?:
, as?
안전한 연산을 위한 안전 연산자!!
안전하지 못한 참조를 위한 연산자 (Not Null Assertion)let
널 안정성 검증한 결과를 널이 될수 없는 타입을 받아들이는 함수에게 전달해주는 라이브러리 함수