[TIL]Kotiln 기본 문법 : Null과 지연초기화

지혜·2023년 11월 21일

Android_TIL

목록 보기
2/70

✏231121 화요일 TIL(Today I learned) 오늘 배운 것

📖Nullable(?,물음표)

  • 코틀린에서는 기본 변수에 null이 입력되지 않기 때문에, null을 입력하기 위해서는 변수의 타입 뒤에 ?(Nullable)을 입력해줘야 한다.
  • null 포인터 예외가 발행하면 프로그램이 다운되기 때문에 Null관리는 중요하다.

1. 변수에 null 허용을 설정한 모습

var variable: String?
variable = null

2. 함수에 null 허용을 설정한 모습

fun nullParameter(string: String?){ 

	//함수의 파라미터가 null을 허용하려면 이렇게 if문으로 null 체크를 먼저 해야 사용할 수 있다.
	if (string != null) {  
      var length = string.length
  }
}

3. 함수의 return타입에 null 허용을 설정한 모습

fun nullReturn(): String? {
 	//리턴타입에 NUllable을 지정해줘야지 null을 반환할 수 있다.
 	return null
}

📖Safe call(?.)과 Elvis Operator(?:)

1. Safe call (?.)

fun testSafeCall(str: String?): Int? {
    var resultNull: Int? = str?.length
    
    return resultNull
    //str이 null이면 뒤의 length를 호출하지 않고 null을 반환
}
  • Nullable 변수 뒤에 ?. 가 오면, 해당 변수가 null일 때 뒤에 오는 속성이나 명령어를 처리하지 않는다.

2. Elvis Operator (?:)

fun testElvis(str: String?): Int {
    var resultNonNull: Int = str?.length ?: 33
    
    return resultNonNull
    // length 오른쪽에 ?:을 사용하면 null일 경우 ?: 오른쪽의 값 33이 반환
}
  • Safe call 뒤에 호출되는 프로퍼티 다음에 ?: 를 붙이면, 해당 변수가 null인 경우 ?: 뒤에 오는 값을 기본값으로 사용한다.

📖Nullable로 선언하는 지연초기화

class Person {
	
    var name: String? = null //처음에 null값을 입력해두고,
    init {
        name = "Lionel"
    }
    
    
    fun process() { //메서드 영역에서 값을 입력.
        name?.plus(" Messi")
        print("이름의 길이 = ${name?.length}")
        print("이름의 첫 글자 = ${name?.substring(0, 1)}")
    }
}
  • ?을 사용하여 초기화 할 프로퍼티에 null을 허용 한다.
  • Safe call을 활용하여 사용할 수 있으나, 가독성 면에서 떨어지는 문제가 있다.

📖Nullable을 사용하지 않는 지연초기화

1. lateinit

class Person {
    lateinit var name: String
    init { 
        name = "Lionel"
    }
    fun process(){ //Safe call을 사용하지 않고 사용이 가능하다.
        name.plus(" Messi")
        print("이름의 길이 = ${name.length}")
        print("이름의 첫 글자 = ${name.substring(0, 1)}")
    }
}
  • lateinit는 var로 선언된 프로퍼티에만 사용할 수 있다.
  • Int, Long, Double, Float 등의 기본자료형에는 사용할 수 없다.
  • null이 허용되지 않는다. (변수를 미리 선언만 해놓은 것)
    ※따라서, 초기화되지 않고 메서드나 프로퍼티를 참고하면 null예외 발생으로 앱이 종료된다.
  • 변수가 초기화 되지 않는 상황이 발생하는 경우에는 비추천
    (->Nullable이나 빈 값으로 초기화 하는 것이 좋다.)

2. by lazy

class Company {

	//반환되는 값의 타입을 추론할 수 있기 때문에 person 변수의 타입은 생략.
    val person: Person by lazy { Person() }

    fun process(){
        print("person의 이름은 ${person.name}")
    }
}
  • by lazy는 val로 선언된 프로퍼티에만 사용할 수 있다.
  • by lazy 뒤에 코트 블록에 초기화할 값을 써주면 된다.
  • 선언 시에 초기화되기 때문에 init로 따로 초기화 할 필요가 없다.
  • Company 클래스가 초기화 되더라도 바로 Person()으로 초기화 되지 않고, process메서드에서 person.name이 호출되어야 초기화 된다. (리소스가 크면 전체 처리속도에 영향을 주는 문제가 있다.)


✏오늘 발생 문제 및 해결

📖새롭게 알게된 것

  • Null Safety개념이 아주 흥미로웠다. null처리를 위해 따로 ? 연산자를 사용해줘야 한다는 것, 그리고 null값을 대체하기 위한 ?: 연산자가 있는 것도 새로웠다.
    =>Null Safety가 일종의 예외 처리로 사용되고 있는 것 같은데, 이를 통해 예외 처리를 할 일이 많이 줄어들지 빨리 체감해 보고 싶다.

  • 지연초기화의 by lazy도 모양부터 낯선감이 있었는데, 전체처리속도에 유의 하여 사용한다는 주의점을 기억하고 상황에 맞춰 효율적인 방법을 사용할 수있도록 노력해야겠다.

📖오늘의 문제 발생

기본문법서의 예제문제들을 안드로이드 스튜디오로 실행하고 있는데, logcat을 확인해야할 때, 빌드는 제대로 되고 에뮬도 잘 실행되었는데 로그캣만 반응 없이 잠잠해서 당황스러웠다.

📖해결

확인해보니까 일단 사용하고있는 에뮬레이터 이름과 로그캣에 찍혀있는 에뮬레이터 이름이 달라서 이를 중점으로 검색했더니
메뉴의 File > Invalidate Caches / Restart 를 통해 캐시를 모두 지우고 다시 시작하는 방법이 나와서 실행했더니 사용하고 있는 에뮬레이터와 잘 연결되는 것을 볼 수 있었다.
이 방법이 통하지 않는다면
메뉴의 Tools > Android > Android Device Monitor 을 통해서
LogCat창을 확인할 수 있다고 하니, 기억해둬야곘다.

profile
파이팅!

0개의 댓글