본문 바로가기
공부/Kotlin

[Kotlin] 코틀린 타입 시스템 사용해보기

by JERO__ 2022. 6. 20.

1. 널 가능성

  • NullPointerException 오류를 피할 수 있게 돕기 위한 코틀린 타입 시스템의 특성
  • 실행시점 → 컴파일시점 감지

1-1. 널이 될 수 있는 타입

  • 널을 인자로 받을 수 있도록 변경 : 타입이름 뒤 ?를 명시한다.
  • 따라서, 모든 타입은 기본적으로 널이 될 수 없는 타입이다.
  • 널이될 수 있는 타입은 null값을 다루어야 한다!

fun strLenSafe(s: String?): Int = if (s != null) s.length else 0

fun strLenSafe(s: String?): Int = if (s != null) s.length else 0

1-2. 안전한 호출 연산자 ?.

foo?.bar()
  • foo가 null이 아닐 때, 정상 실행 foo.bar()
  • foo가 null일 때, null 반환
    • 에러가 발생하지 않는다.

1-3. 엘비스 연산자 ?:

  • 좌항이, null이 아니면 좌항반환
  • 좌항이, null이면 우항반환

fun strLenSafe(s: String): Int = s.length ?: 0

1-4. 안전한 캐스트 as?

as : 지정한 타입으로 바꿀 수 없으면 ClassCastException이 발생한다.

as? : 지정한 타입으로 바꿀 수 없으면 null을 반환한다.

1-5. null 아님 단언 !!

널이 될 수 없는 타입으로 강제로 바꾼다.

1-6. let 함수

null이 될 수 있는 식을 쉽게 다룰 수 있다.

  • String을 파라미터로 받는 함수 A
  • null이 될 수 있는 타입 String? 은 함수 A의 인자로 전달할 수 없다. 사용하려면,
fun A(email: String) { }
// 1. let 사용X. 검증해주고 넣어야 한다.
if (email != null) A(email) 
// 2. let 사용. String? 에서 String 타입으로 변환하여 사용
email?.let { A(it) }          // ?. 을 사용하여 안전한 호출

1-7. 나중에 초기화할 프로퍼티 lateinit

class MyService {}
class MyTest {
	private lateinit var myService: MyService
	@Before fun setUp() {
		myService = MyService()
	}
}

1-8. null이 될 수 있는 타입 확장

null이 될 수 있는 수신객체에 대해 확장 함수 호출할 수 있다.

fun String?.isNullOrBlank(): Boolean = this == null || this.isBlank()

1-9. 타입 파라미터의 null 가능성

T는 Any? 타입이다.

fun <T> printHashCode(t: T) {
	println(t?.hashCode())          // null이 될 수 있으므로 안전하게 호출
}
fun <Any> printHashCode(t: T) {
	println(t.hashCode())          // null이 들어올 수 없다.
}

2. 코틀린의 원시타입

2-1. 원시타입

원시타입(primitive type) : Int, Boolean

  • 값이 직접 들어감

참조타입(reference type) : String

  • 메모리상의 객체 위치가 들어감
  • 자바는 원시타입을 컬렉션에 담을 수 없다. 래퍼타입으로 원시타입을 감싸 사용한다. Collection<Integer> 처럼 사용해야 한다.
  • 코틀린은 원시타입과 래퍼타입을 구분하지 않는다. 항상 같은 타입을 사용한다.

2-2. 널이 될 수 있는 원시타입 Int? Boolean? …

자바의 래퍼 타입으로 컴파일된다.

2-3. 숫자 변환

자바처럼 숫자가 자동변환 하지 않는다.

val i = 1
val l: Long = i.toLong()

개발자의 혼란을 피할 수 있다. 명시적으로 변환하자

2-4. 최상위타입 Any, Any?

자바의 최상위 타입 : Object

  • 참조타입만

코틀린의 최상위 타입 : Any

  • 원시타입을 포함한 모든 타입조상
  • 참조타입이지만, 원시타입을 대입하면 객체로 감싼다.

2-5. 코틀린의 void Unit타입

코틀린의 Unit타입은 자바의 void와 같은 기능이다.

fun f(): Unit { ... }
fun f() { ... } // 같다
  • 단, Unit을 타입인자로 쓸 수 있다. (void와 차이점)
  • class NoResultProcessor: Processor<Unit> { override fun process() { // return할 필요 없다. } }

2-6. 이 함수는 결코 정상적으로 끝나지 않는다 Nothing 타입

코틀린에는 결코 성공적으로 값을 돌려주는 일이 없어 반환값이라는 개념이 의미 없는 함수가 일부 존재한다.

  • 테스트 라이브러리의 fail함수를 제공하는 경우 (테스트 실패)
  • 무한 루프 함수
fun fail(message: String): Nothing {
	throw IlleagalStateException(message)
}

3. 컬렉션과 배열

3-1. 널 가능성과 컬렉션

  • List<Int?> : 리스트 안의 각 값이 널이될 수 있다.
  • List<Int>? : 전체 리스트가 널이될 수 있다.
  • List<Int?>? : 이렇게 사용할수도 있다.

3-2. 읽기전용 컬렉션, 변경가능한 컬렉션

Collection

  • 원소 추가, 제거 메서드가 없다

MutableCollection

  • add
  • remove
  • clear

가능하면 항상 읽기 전용 인터페이스를 사용하는 것을 일반적인 규칙으로 삼자.

 

kotlin in action 책을 통한 공부입니다.

 

댓글