DTO 생성하기 (POJO/POCO)
data class Customer(val name: String, val email: String)
`Customer` 클래스는 다음과 같은 기능들을 제공합니다:
- 모든 속성들의 getters (그리고 `var` 일 땐 setter 도)
- `equals()`
- `hashCode()`
- `toString()`
- `copy()`
- `component1()`, `component2()`, ...,
함수 인자들에 기본 값 지정하기
fun foo(a: Int = 0, b: String = "") { ... }
이렇게 지정해 두면, 호출 할 때 `a`, `b` 없이 `foo()` 라고 호출 할 수 있다.
list 필터링
val positives = list.filter { x -> x > 0 }
짧게 하려면
val positives = list.filter { it > 0 }
collection 에서 특정 요소가 존재하는지 확인하기
if ("john@example.com" in emailsList) { ... }
if ("jane@example.com" !in emailsList) { ... }
문자열 보간
println("Name $name")
안전하게 표준 입력 읽기
// 만일, 입력이 정수로 변환할 수 없다면, 문자열을 읽고 null 을 반환한다. 예제: Hi there!
val wrongInt = readln().toIntOrNull()
println(wrongInt)
// null
// 문자열을 읽어서 문자열을 정수로 변환하고 정수를 반환한다. 예제: 13
val correctInt = readln().toIntOrNull()
println(correctInt)
// 13
인스턴스 확인
when (x) {
is Foo -> ...
is Bar -> ...
else -> ...
}
복잡하게 if/else 체인을 쓰지 않고 `when` 으로 깔끔하게 처리할 수 있다.
읽기 전용 list
val list = listOf("a", "b", "c")
읽기 전용 map
val map = mapOf("a" to 1, "b" to 2, "c" to 3)
map 요소에 접근하기
println(map["key"])
map["key"] = value
map 또는 list 쌍 탐색하기
for ((k, v) in map) {
println("$k -> $v")
}
`k` 와 `v` 는 map 의 key 와 value 를 읽기 쉽게 사용한것이다. 실제로 구현할 때, `age`, `name` 등이 key 에 사용된다.
게으른 속성
val p: String by lazy { // 이 값은 첫번째 접근시에만 계산되어집니다.
// 문자열 계산
}
해당 변수가 메모리에 적재 될 때도 `p` 는 어떤 값도 가지고 있지 않다가, 어디선가 `p` 에 접근하게 되면 그 때 구현 된 값이 적용된다.
함수 확장하기
fun String.spaceToCamelCase() { ... }
"Convert this to camelcase".spaceToCamelCase()
이런 식으로 기존에 존재하는 클래스들에 함수를 추가하거나 재정의할 필요 없이 손 쉽게 추가할 수 있다.
싱글톤 생성하기
object Resource {
val name = "Name"
}
static class 처럼 인스턴스 생성 없이 바로 사용이 가능한 객체
Use inline value classes for type-safe values
@JvmInline
value class EmployeeId(private val id: String)
@JvmInline
value class CustomerId(private val id: String)
if you accidentally mix up `EmplyeeId` and `CustomerId`, a compilation error is triggered.
Note: The @JvmInline annotation is only needed for JVM backends.
추상화 클래스 인스턴스화 하기
abstract class MyAbstractClass {
abstract fun doSomething()
abstract fun sleep()
}
fun main() {
val myObject = object : MyAbstractClass() {
override fun doSomething() {
// ...
}
override fun sleep() { // ...
}
}
myObject.doSomething()
}
if-not-null 속기
val files = File("Test").listFiles()
println(files?.size) // size is printed if files is not null
files 가 null 일 경우, NPE 가 발생할 텐데, kotlin 은 `?` 를 사용해 짧고 쉬우면서 안전하게 처리할 수 있다. 이게 싫으면 `if/else` 로 null-safe 하게 바꿔줘야한다.
if-not-null-else 속기
val files = File("Test").listFiles()
// For simple fallback values:
println(files?.size ?: "empty") //files 가 null 이면 "empty" 가 출력되고, 그렇지 않으면 files.size 가 출력된다.
// files 가 null 이면 run block 에서 계산되어 반환된 값을 사용.
val filesSize = files?.size ?: run {
val someSize = getSomeSize()
someSize * 2
}
println(filesSize)
null 이면 statement 실행하기
val values = ...
val email = values["email"] ?: throw IllegalStateException("Email is missing!")
비어있을 수 있는 collection 에서 첫번째 아이템 얻기
val emails = ... // might be empty
val mainEmail = emails.firstOrNull() ?: ""
if/else 로 확인할 필요 없이 안전하게 "" 로 가져올 수 있다.
null 이 아닐 때 실행하기
val value = ...
value?.let {
... // execute this block if not null
}
null 이 아닐 때 nullable 한 값에 매핑하기
val value = ...
val mapped = value?.let { transformValue(it) } ?: defaultValue
// defaultValue 는 value 또는 transformValue 결과가 null 일 때 반환된다.
예외가 생겼을 때 반환하기
fun transform(color: String): Int {
return when (color) {
"Red" -> 0
"Green" -> 1
"Blue" -> 2
else -> throw IllegalArgumentException("Invalid color param value")
}
}
try/catch 표현식
fun test() {
val result = try {
count()
} catch (e: ArithmeticException) {
throw IllegalStateException(e)
}
// Working with result
}
if 표현식
val y = if (x == 1) {
"one"
} else if (x == 2) {
"two"
} else {
"other"
}
Unit 을 반환하는 빌더 스타일의 메소드 사용법
fun arrayOfMinusOnes(size: Int): IntArray {
return IntArray(size).apply { fill(-1) }
}
함수 단일 표현법
fun theAnswer() = 42
이와 동일한 것은:
fun theAnswer(): Int {
return 42
}
이것은 효과적으로 다른 사용법들과 결합하여 더 짧은 코드로 구현될 수 있다. 예를 들어 `when` 표현식:
fun transform(color: String): Int = when (color) {
"Red" -> 0
"Green" -> 1
"Blue" -> 2
else -> throw IllegalArgumentException("Invalid color param value")
}
하나의 객체의 여러개 메서드들을 호출하기
class Turtle {
fun penDown()
fun penUp()
fun turn(degrees: Double)
fun forward(pixels: Double)
}
val myTurtle = Turtle()
with(myTurtle) { //draw a 100 pix square
penDown()
for (i in 1..4) {
forward(100.0)
turn(90.0)
}
penUp()
}
하나의 객체의 속성들 설정하기
val myRectangle = Rectangle().apply {
length = 4
breadth = 5
color = 0xFAFAFA
}
이것은 객체 생성자에 존재하지 않는 속성들을 구성하는데 유용함.
Java 7 의 try-with-resources
val stream = Files.newInputStream(Paths.get("/some/file.txt"))
stream.buffered().reader().use { reader ->
println(reader.readText())
}
Generic 타입 정보가 필요한 Generic 함수
// public final class Gson {
// ...
// public <T> T fromJson(JsonElement json, Class<T> classOfT) throws JsonSyntaxException {
// ...
inline fun <reified T: Any> Gson.fromJson(json: JsonElement): T = this.fromJson(json, T::class.java)
두개의 값 교환하기
var a = 1
var b = 2
a = b.also { b = a }
구현이 필요한 코드 표시하기
코틀린 표준 라이브러리는 `TODO()` 함수를 가지고 있음. 그것은 항상 `NotImplementedError` 를 발생시킴. 이 반환 자료형은 `Nothing` 이기에 자료형을 예측할 필요가 없음. 또한 reason 인자에 접근해서 값을 덮어쓸 수 있음.
fun calcTaxes(): BigDecimal = TODO("Waiting for feedback from accounting")
Intellij Idea 의 코틀린 플러긴은 TODO() 의 의미를 이해하고 TODO 도구 창에 코드 위치를 자동으로 추가함.
'프로그래밍언어 > Kotlin' 카테고리의 다른 글
Kotlin 기본 문법 (0) | 2025.02.04 |
---|