[TIL] #4 Kotlin Basic Syntax 2

Yeon·2023년 7월 20일
0
post-thumbnail

💡 Visibility Modifiers

접근제한자설명
public기본 접근 제한자로써 명시하지 않으면 기본적으로 public, 어디에서나 접근 가능
private해당 파일이나 클래스에서만 접근 가능
protected상속받은 인터페이스, 클래스 또는 자식 클래스에서만 접근 가능
internal같은 모듈 내에서는 접근 가능
  • 접근 제한자를 아무것도 붙이지 않으면 public으로 선언됨
  • 접근 제한자를 가질 수 있는 요소: class, object, interface, constructor, function, property
  • 로컬 변수, 로컬 함수, 로컬 클래스는 접근 제한자를 선언할 수 없음
  • 장점
    • 접근 제한을 통해 데이터에 무분별한 접근을 막을 수 있음
    • 유지보수가 용이함

➕ Term

  • project 최상단 개념, <module, peckage, class>를 포함
  • module 프로젝트 아래의 개념, <package, class>를 포함
  • package 모듈 아래의 개념, <class>를 포함



💡 Exception Handling

  • Exception 프로그램 실행 중 예기치 못한 에러가 발생하는 경우
  • 예외처리를 통해 사용자 입장에서 어떤 이유 때문에 어떤 에러가 발생했는지 안내하거나 프로그램이 강제 종료되는 것을 방지할 수 있음
  • 미리 예외를 생각하고 소스코드를 작성하여 안정성을 높일 수 있음

1. try - catch

try-catch-structure

  • try 블록 내에서 예외가 발생하면, catch 블록으로 이동하여 예외를 처리하고 다음 코드를 계속 실행
  • catch 블록은 해당 예외의 종류를 지정하여 처리할 수 있음
  • 하나의 try 블록에 여러 개의 catch 블록 사용 가능
while (true) {
    try {
        var num = readLine()!!.toInt()
        println("Input: $num")
        break
    }
    catch (e: java.lang.NumberFormatException) {
        println("Please enter a number.")
    }
}

2. throw

throw-structure

  • 개발자가 직접 예외를 발생시키는 키워드
    • 예외가 발생할 조건을 프로그래머가 확인하고, 해당 조건이 충족되면 throw 키워드를 사용하여 특정 예외를 생성하고 던짐
    • 이후 throw로 던진 예외는 프로그램 실행 흐름을 중단 시키고, 해당 예외를 처리하는 부모 호출 스택에 위치한 catch 블록으로 이동함
while (true) {
    try {
        var num = readLine()!!.toInt()
        println("Input: $num")
        break
    } catch(e: java.lang.NumberFormatException) {
        println("Please enter a number.")
    } finally {
        println("The connection with keyboaed is normal.")
    }
}

3. throw & try-catch

  • 개발자가 예외를 생성하고 발생시키는 것과 그 예외를 처리하는 부분으로 나누어 역할을 수행하게 할 수 있음
  • 이렇게 하면 프로그램이 예외 상황에 안정적으로 대응할 수 있음
fun divide(x: Int, b: Int): Int {
    if (y==0) {
        throw ArithmeticException("Divisor cannot be zero")
    }
    return a / b
}

fun main() {
    try {
        val result = divide(10,0)
        println("Result: $result")
    } catch(e: ArithmeticException) {
        println("Caught an exception: $e.message")
    } finally {
        println("Finally block executed.")
    }
}


// [output]
// Caught and exception: Divisor cannot be zero.
// Finally block executed.



💡 Lazy Intializtion

  • var 또는 val의 값이 처음 사용되기 전까지 초기화를 지연시키는 것을 의미
  • 필요할 때만 수행하여 성능을 최적화할 수 있음
  • 저사양으로 제한되어 있는 환경에서는 메모리를 더욱 효율적으로 사용할 수 있음
  • var나 val의 값을 Non-Nullable 타입으로 선언해야 하며, 초기화 전에는 접근할 수 없음

1. lateinit

  • 미리 변수를 선언해놓고 이후에 값을 할당함
  • var 변수만 사용 가능
    • var 변수는 초기화 이후에도 값을 변경할 수 있기 때문
  • 기본 자료형 Int, Boolean, Double, Char 등의 자료형에는 사용할 수 없음
  • getter, setter에도 사용할 수 없음
  • 초기화 확인 여부는 var 변수 이름 앞에 :: (콜론 2개)를 붙이고 .isInitialized를 사용
  • 변수를 선언한 뒤 초기값 할당 전에 lateinit 변수를 사용하면 아래와 같이 초기화되지 않았다는 UninitializedPropertyAccessException 예외가 발생함
    Exception in thread "main" kotlin.UninitializedPropertyAccessException: lateinit property b has not been initialized
fun main() {
    val x = Test()
    
    println(x.getTest())
    x.text = "new value"  // 변수 초기화
    println(x.getTest())
}

class Test() {
    lateinit var text: String  // Non-Nullable로 선언
    
    fun getTest(): String {
        if (::text.isInitialized) {
            return text
        } else {
            return "default"
        }
    }
}


// [output]
// default
// new value

2. lazy

  • 변수를 실행하는 시점까지 초기화를 처음 사용될 때까지 미룰 수 있으며, 이후에는 캐싱된 값을 사용함
  • val 변수만 사용 가능
    • val 변수는 읽기 전용으로 값이 변경되지 않아야 하기 때문
  • val 변수를 선언한 뒤, by lazy를 붙이고 람다함수를 정의해주면 됨
fun main() {
    val num: Int by lazy {
        println("Initialized")
        7
    }
    println("Start the code")
    println(num)
    println(num)
}


// [output]
// Start the code
// Initialized
// 7
// 7
val lazyValue: String by lazy {
    println("Ars")
    "Hello"
}

fun main() {
    println(lazyValue)  // 처음 접근 시에만 Ars와 캐싱된 값인 Hello 출력
    println(lazyValue)  // 캐싱된 값인 Hello 출력
}


// [output]
// Ars
// Hello
// Hello



💡 Null Safety

  • NullPointerException (NPE)과 같은 오류를 방지하고 프로그램의 안정성을 향상시킴
  • 코틀린에서는 변수의 타입에 null이 허용되는지 여부를 명시적으로 지정할 수 있음
    • Nullalbe
    • Non-Nullable

1. Nullable

  • ?
  • 변수의 값이 null이 될 수 있음
  • ex. var.name: String? = null

2. Non-Nullable

  • !!
  • 변수의 값이 null이 될 수 없음 (항상 특정 타입의 값을 가져야 함)
  • 만약 해당 변수가 null이라면 NullPorinterException이 발생할 수 있음
    • null이 아님을 확신할 때만 사용해야 함
    • Nullable 체크와 안전한 null 처리 방법을 사용하면 !!를 사용해도 됨
  • ex. val length: Int = name!!.length

3. Safe Calls

  • ?.
  • Nullable 타입의 변수나 표현식 뒤에 붙여서 안전하게 호출함
  • 변수가 null이면 메소드 호출이나 프로퍼티 접근을 진행하지 않고 null을 반환함
  • ex. val length: Int? = name?.length

4. Elvis Operator

  • ?:
  • null이 아닌 값을 얻기 위해 사용
  • ex. val result: Int = nullableValue ?: defaultValue
    • 왼쪽 표현식이 null이 아닌 경우에는 왼쪽 표현식의 값을 사용
    • 왼쪽 표현식이 null인 경우에는 오른쪽 표현식의 기본값을 사용



[참고 사이트]

'(Kotlin) 접근 제한자에 대해(public, private...)', dev.jaehyeon
'코틀린에서 예외처리하기(try catch, throw)', IT에 취.하.개
'[Kotlin] 코틀린 lateinit, lazy로 늦은 초기화, 초기화 지연', 신입개발자 쩨리
'[Kotlin] 코틀린의 널 안정성(Null Safety', devlog of ShinJe Kim

1개의 댓글

comment-user-thumbnail
2023년 7월 20일

소중한 정보 감사드립니다!

답글 달기