Lewis's Tech Keep
[Kotlin] 코틀린 적응기 - 변수, 타입, 연산자 본문
시작
이번에 코틀린을 쓰게 될 기회가 생길 것 같아서 코틀린 입문 강의를 하나 구입하였다.
아직 section2 중반까지만 들었는데 재밌어서 정리를 남겨보려고 한다.
쉽고 재밌고 예제도 다양해서 즐겁게 하고 있다.
배우고 있는 것
https://www.inflearn.com/course/java-to-kotlin
1. 변수
변수는 var과 val이 있다.
var(variable)는 값을 한번 할당하고 나서도 계속 바꿀 수 있는 mutable한 값이다.
val(value)는 값을 한번 할당하고나면 바꿀 수 없는 immutable한 값이다.
(final 키워드를 쓴 것과 비슷한 효과지만 nullable 표시를 해주면 처음에 할당하지 않아도 되는 차이가 있다.)
또한 nullable한 값일 경우 nullable을 명시 해 줄 수 있다.
어떤 타입을 선언 해 준 후에 ?를 붙이면 해당 값은 nullable 해질 수 있다는 뜻
그리고 객체 생성 시에 Java에서는 new Person() 과 같이 선언이 필요하지만 Kotlin에서는 Person()만으로 생성이 된다.
fun main() {
// variable mutable 한 변수
var number1: Long = 10L
// value immutable 한 변수 (final과 같은 느낌)
val number2 = 100L
// nullable 선언
var number3: Long? = 1_000L // nullable, val 괜찮다.
number3 = null
// 객체 생성
var person = Person("hihi") // no new keyword
}
2. Nullable
먼저 함수 파라메터를 nullable하게 받고 싶다면 타입 뒤에 ?를 추가하여 nullable하게 받을 수 있는 값임을 명시한다.
// nullable parameter function throw exception
fun startsWithA1(str: String?): Boolean {
if (str == null) {
throw IllegalArgumentException("null hi")
}
return str.startsWith("A")
}
return 하는 값도 특정 값이 아닌 null 값을 return 하고 싶다면 return 타입에도 ? 를 붙여준다.
// nullable parameter function return nullable
fun startsWithA2(str: String?): Boolean? {
if (str == null) {
return null
}
return str.startsWith("A")
}
str == null 과 같은 코드들은 잘못하면 실수 할 가능성도 있는 코드라고 생각하는데,
이 때 safe call을 쓰면 ?로 값이 없을 수 있고 없는 경우 null 을 반환한다는 것을 알릴 수 있다.
// nullable parameter function safe call
fun startsWithA2SafeCall(str: String?): Boolean? {
return str?.startsWith("A")
}
elvis 연산자(?:)를 이용하면 null일 때 어떤 행동을 할 것인지 뒤에 적을 수 있다.
예제는 에러를 던져보았다.
// nullable parameter function elvis operator
fun startsWithA2Elvis(str: String?): Boolean {
return str?.startsWith("A")
?: throw IllegalArgumentException("hihi")
}
early return 해줄 때 elvis 연산자를 이용하면 이런식으로도 가능하다. (null 일 때 false 반환)
// nullable parameter function early return
fun startsWithEarlyReturn(str: String?): Boolean {
str ?: return false
return str.startsWith("A")
}
엔티티와 같이 처음에 받을 때는 null이지만 실제로 작동할 때는 non-null인 경우에
일단 parameter 연산자는 ? 를 선언하지만 !!를 통해 해당 변수가 non-null임을 선언할 수 있다.
// not nullable
// runtime npe exception
fun startsWithNotNull(str: String?): Boolean {
return str!!.startsWith("A")
}
3. 타입
코틀린은 타입 선언이 중요하기에 타입 변경 시
암시적으로 바뀌는 Java와는 달리 toLong()과 같은 메서드를 이용하여 명시적 변경을 해주어야 한다.
fun main() {
// type 의 명시적 변경이 필요함
val number1: Int? = 3
var number2: Long = number1?.toLong() ?: 0L
}
객체 생성 시에 타입 선언 시 as를 넣어주면 타입을 선언할 수 있다.
그렇지만 as를 선언하지 않아도 기본적으로 되긴한다.
fun main() {
// null 로 불러보기 (해당 함수는 nullable하지 않기 때문에 런타임 npe가 발생함)
printAgeIfPerson(null)
// person 예제
printAgeIfPerson(Person("", 10))
}
fun printAgeIfPerson(obj: Any) {
if (obj is Person) {
val person = obj as Person // 생략해도 알아서 타입 추론 해 주는 듯
println(person.age)
}
}
nullable하게 타입을 받아주게 하려면 일단 Any? 로 받은 후에 as? 를 통해 null한 값도 받을 수 있다.
fun main() {
// null 로 불러보기
printAgeIfNotPerson(null)
// person 예제
printAgeIfNotPerson(Person("", 10))
}
fun printAgeIfNotPerson(obj: Any?) {
// 생략해도 알아서 타입 추론 해 주는 듯
// nullable 할 때
val person = obj as? Person
println(person?.age)
}
string.format 같이 변수가 들어간 어떤 string 구문을 쓰고 싶을 경우 활용할 수 있는 방법들
fun main() {
// String interpolation String Indexing
val person = Person("hi", 100)
val log = "사람 이름 ${person.name} 이고 나이는 ${person.age}세 입니다"
println(log)
// trim indent
val log2 = """
ABC
DFG
${person.name}
""".trimIndent()
println(log2)
// get index string
println(log2[0])
}
그 외 특이한 타입들
Any 타입
Java의 Object와 같은 최상위 객체 타입, 뭐든 받을 수 있다.
Unit 타입
Java 타입 중에 void 타입과 비슷하다. 아무것도 반환하지 않는 것 처럼 보이지만 실제로는 Unit을 return 하고 있는 것이다.
아무 타입을 명시하지 않고 함수를 사용한다면 Unit 타입을 반환한다고 생각하면 된다.
fun sayHello(): Unit {
println("Hello!")
}
Nothing 타입
무한 반복 루프나 아무것도 하지않고 예외만 던지는 것에 사용 (실제로 사용은 잘 안한다고 함)
fun fail(message: String): Nothing {
throw IllegalArgumentException("")
}
4. 연산자
>, < 와 같은 부등호만 써도 compareTo를 자동으로 읽는다.
fun main() {
val money1_1 = JavaMoney(2_000L)
val money1_2 = JavaMoney(1_000L)
// automatically check compareTo with operators only
if (money1_1 > money1_2) {
println("ok")
}
}
새로운 객체를 생성하고 == 로 주소 비교를 하더라도 equals를 실행하기 때문에 equals가 설정되어있다면 true다.
equals 없이 data class로 하면 java와 같이 false인 것을 확인함.
fun main() {
val money2_1 = JavaMoney(1_000L)
val money2_2 = money2_1
val money2_3 = JavaMoney(1_000L)
// true
println(money2_1 == money2_3)
}
아래의 경우 자바라면 money3_1.plus(money3_2)를 불러주어야 하지만 코틀린에서는 money3_1 + money3_2 로 해결된다.
fun main() {
// 연산자 overloading
val money3_1 = Money(1_000L)
val moeny3_2 = Money(2_000L)
println(money3_1 + moeny3_2)
}
data class Money (
val amount: Long
) {
operator fun plus(other: Money): Money {
return Money(this.amount + other.amount)
}
}
'Kotlin > Kotlin 적응기' 카테고리의 다른 글
[kotlin] 코틀린 적응기 - 배열 & 컬렉션, 함수 (0) | 2024.10.01 |
---|---|
[Kotlin] 코틀린 적응기 - 중첩 클래스, data class & enum class & sealed class (0) | 2024.10.01 |
[Kotlin] 코틀린 적응기 - 접근 제어, object (0) | 2024.10.01 |
[Kotlin] 코틀린 적응기 - 클래스, 상속 (1) | 2024.10.01 |
[Kotlin] 코틀린 적응기 - 제어문, 반복문, 예외, 함수 (0) | 2024.09.30 |