Chef.Yeon
Code Cook
Chef.Yeon
전체 방문자
오늘
어제
  • 분류 전체보기 (230)
    • 게임 개발 (1)
      • Unity (1)
    • Android (27)
      • Kotlin (19)
      • 우아한테크코스 5기 (4)
    • Language (11)
      • 파이썬 (3)
      • Java (7)
    • DB (2)
      • SQL (16)
    • Spring (25)
    • 코딩테스트 (56)
    • Git (1)
    • TIL (85)
    • DevOps (6)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • grafana
  • kibana
  • 안드로이드
  • 프리코스
  • 파이썬
  • 프로그래머스
  • SQL
  • Docker
  • 다이나믹 프로그래밍
  • 백준
  • 레포지토리
  • 내림차순
  • til
  • rsocket
  • ec2
  • java
  • enum
  • 우아한테크코스
  • 코틀린 인 액션
  • 에라토스테네스의 체
  • 코딩테스트
  • MariaDB
  • spring
  • webflux
  • Android
  • 코틀린
  • elasticsearch
  • Wil
  • kotlin
  • 문자열

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
Chef.Yeon

Code Cook

Android/Kotlin

[코틀린 인 액션] 6장 정리: null 다루는 방법

2022. 11. 30. 21:03
6.1.3 안전한 호출 연산자 

   1. 호출하려는 값이 null이 아니면 일반 메서드 호출처럼 작동

   2. 호출하려는 값이 null이라면 호출이 무시되고 null이 결과 값

fun main(args: Array<String>) {
    printAllCaps("abc")
    printAllCaps(null)
}

fun printAllCaps(s: String?) {
    val allCaps: String? = s?.uppercase()
    println(allCaps)
}

 

   2. ?. 연산자를 사용하여 안전한 호출 연쇄

class Address(val streetAddress: String, val city: String, val country: String)

class Company(val name: String, val address: Address?)

class Person(val name: String, val company: Company?)

fun Person.countryName(): String {
    val country = this.company?.address?.country
    return if (country != null) country else "UnKnown"
}

fun main(args: Array<String>) {
    val person = Person("Alice", null)
    println(person.countryName())
}

 

6.1.4 엘비스 연산자: ?:

   1. null 대신 사용할 디폴트 값을 지정할 때 사용 가능

   2. 좌항 값이 null이 아니면 좌항 값을 결과 값으로 하고, null이면 우항 값을 결과 값으로 함

fun main(args: Array<String>) {
    println(foo("Hello"))
    println(foo(null))
}

fun foo(s: String?): String {
    return s ?: "nulling"
}

 

class Address(val streetAddress: String, val city: String, val country: String)

class Company(val name: String, val address: Address?)

class Person(val name: String, val company: Company?)

fun Person.countryName() = company?.address?.country ?: "Unknown"

fun main(args: Array<String>) {
    val person = Person("Alice", null)
    println(person.countryName())
}

 

   3. 엘비스 연산자의 우항에 return, throw 등의 연산을 넣을 수 있음

fun Person.countryName() = company?.address?.country ?: "Unknown"

fun printShippingLabel(person: Person) {
    val address = person.company?.address ?: throw IllegalArgumentException("No address")
    with(address) {
        println(streetAddress)
        println("$zipCode $city, $country")
    }
}

fun main(args: Array<String>) {
    val address = Address("Elsestr. 47", 80687, "Munich", "Germany")
    val jetbrains = Company("JetBrains", address)
    val person = Person("Alice", jetbrains)
    val person2 = Person("Bob", null)
    printShippingLabel(person)
    printShippingLabel(person2)
}

 

6.1.5 안전한 캐스트: as?

   1. 어떤 값을 지정한 타입으로 변환할 수 없으면 null을 반환

class Person(val firstName: String, val lastName: String) {
    override fun equals(other: Any?): Boolean {
        val otherPerson = other as? Person ?: return false

        return otherPerson.firstName == firstName &&
                otherPerson.lastName == lastName
    }
}

fun main(args: Array<String>) {
    val person = Person("Dmitry","Jemerov")
    val person2 = Person("Dmitry","Jemerov")
    println(person == person2)
    println(person.equals(42))
}

 

6.1.6 널 아님 단언: !!

   1. 느낌표를 이중으로 사용하여 어떤 값이든 null이 될 수 없는 타입으로 강제 변환

fun ignoreNulls(s: String?) {
    val sNotNull: String = s!!
    println(sNotNull.length)
}

fun main(args: Array<String>) {
    ignoreNulls(null)
}

 

   2. 단, !!를 null에 대해 사용해서 발생하는 예외의 스택 트레이스에는 어떤 파일의 몇 번째 줄인지에 대한 정보는
      들어있지만, 어떤 식에서 예외가 발생했는지에 대한 정보가 들어있지 않음

   - 어떤 값이 null이었는지 확실히 하기 위해 여러 !! 단언문을 한 줄에 쓰는 것을 피할 것

person.company!!.address!!.country

 

6.1.7 let 함수
fun sendEmailTo(email: String) {
    /* ... */
}
if (email != null) sendEmailTo(email)

   -> sendEmailTo 함수는 null이 될 수 없는 타입의 값을 파라미터로 받기 때문에 인자를 넘겨주기 전에,
       주어진 값이 null 값인지 검사해야함

   -> let 함수를 통해 인자를 전달할 수 있음

 

   1. 안전한 호출 연산자와 함께 사용하면 원하는 식을 평가해서 결과가 null인지 검사한 후,
       그 결과를 변수에 넣는 작업을 간단히 수행할 수 있음

   2. null이 될 수 있는 값에 대해 안전한 호출 구문을 사용해 let을 호출하되,

       null이 될 수 없는 타입을 인자로 받는 람다를 let에 전달

fun main(args: Array<String>) {
    val email: String? = "test@naver.com"
    email?.let {
        email -> sendEmailTo(email)
    }
}

 

   3. it을 사용하여 인자 전달이 가능

fun sendEmailTo(email: String) { // 널이 될 수 없는 파라미터
    println("sending email to $email")
}

fun main(args: Array<String>) {
    val email: String? = "test@naver.com"
    email?.let { sendEmailTo(it) }

    val email2: String? = null
    email2?.let { sendEmailTo(it) } // 아무 일도 일어나지 않음
}

 

   4. 여러 값이 null인지 검사 -> let 호출을 중첩시켜 사용

     - But. let을 중첩시켜 처리하면 코드가 복잡해져 알아보기 어려우므로, 일반적인 if를 사용해 모든 값을 한꺼번에
       검사하 는 것이 나음

 

6.1.8 나중에 초기화할 프로퍼티

   1. lateinit 변경자를 통해 프로퍼티를 나중에 초기화 할 수 있음

    - 나중에 초기화할 프로퍼티는 항상 var이어야 함

class MyService {
    fun performAction(): String = "foo"
}

class MyTest {
    // 초기화하지 않고 null이 될 수 없는 프로퍼티 선언
    private lateinit var myService: MyService
    
    @Before
    fun setUp() {
        myService = MyService()
    }
    
    @Test
    fun testAction() {
        Assert.assertEqauls("foo", myService.performAction())
    }
}

 

6.1.10 타입 파라미터의 널 가능성

   1. 함수나 클래스의 코든 타입 파라미터는 기본적으로 null이 될 수 있음

     - 타입 파라미터 T를 클래스나 함수 안에서 타입 이름으로 사용하면 이름 끝에 물음표가 없더라도
       T가 null이 될 수 있는 타입

fun <T> printHashCode(t: T) {
    println(t?.hashCode())
}

fun main(args: Array<String>) {
    printHashCode(null)
}

 

   2. 타입 파라미터가 null이 아님을 확실히 하기 위해서는 null이 될 수 없는 타입 상한을 지정해야함

타입 상한을 지정하여 null을 인자로 넘겨주면 에러 발생

728x90

'Android > Kotlin' 카테고리의 다른 글

[코틀린 인 액션] 8장 정리: 고차 함수  (0) 2022.12.13
[코틀린 인 액션] 7장 정리: 연산자 오버로딩  (0) 2022.12.05
[코틀린 인 액션] 5장 정리  (0) 2022.11.30
[코틀린 인 액션] 4장 정리  (0) 2022.11.29
[코틀린 인 액션] 3장 정리  (0) 2022.11.28
    'Android/Kotlin' 카테고리의 다른 글
    • [코틀린 인 액션] 8장 정리: 고차 함수
    • [코틀린 인 액션] 7장 정리: 연산자 오버로딩
    • [코틀린 인 액션] 5장 정리
    • [코틀린 인 액션] 4장 정리
    Chef.Yeon
    Chef.Yeon
    보기 좋고 깔끔한 코드를 요리하기 위해 노력하고 있습니다.

    티스토리툴바