Chapter 7 ๋น์ฉ
์ค๋๋ ์ ์ฝ๋์ ํจ์์ฑ(efficiency) ๋ฅผ ๊ด๋ํ๊ฒ ๋ฐ๋ผ๋ณธ๋ค.
์ด๋ ๋ฉ๋ชจ๋ฆฌ๊ฐ ์ ๋ ดํด์ง๊ณ ๊ฐ๋ฐ์๋ ๋น์ธ์ก๊ธฐ ๋๋ฌธ์ด๊ณ ๋ง์ ์๋ฒ๋ฅผ ์ด์ํ๋ค๊ณ ๊ฐ์ ํ ๋์ต์ ํ๋ฅผ ํ๋ฉด ์ด๋ฌํ ๋น์ฉ์ ์ค์ผ์ ์๋ค.
ํ๋ก๊ทธ๋จ์ ํจ์จ์ ์ผ๋ก ๋ง๋ค ๋ ํ์ฉํ ์ ์๋, ์๋ ๊ฒ์ด ๊ฑฐ์ ์๋ ๋ช๊ฐ์ง ๊ณ ์ ๋ ๊ท์น์ด ์๋ค.
์ด๋ฅผ ํ์ฉํ๋ฉด ๋น์ฉ์ ๋ค์ด์ง ์๊ณ ๋ ์ฑ๋ฅ์ ํฌ๊ฒ ํฅ์์ํฌ ์ ์๋ค.
๊ฐ๋ ์ฑ๊ณผ ์ฑ๋ฅ ์ฌ์ด์ ํธ๋ ์ด๋ ์คํ(trade-off)๊ฐ ๋ฐ์ํ ๋, ๊ฐ๋ฐํ๋ ์ปดํฌ๋ํธ์์ ๋ฌด์์ด ๋ ์ค์ํ์ง ์ค์ค๋ก ๋ตํ ์ ์์ด์ผ ํ๋ค.
Item 45 ๋ถํ์ํ ๊ฐ์ฒด ์์ฑ์ ํผํ๋ผ
๊ฐ์ฒด ์์ฑ์ ์ธ์ ๋ ๋น์ฉ์ด ๋ค์ด๊ฐ๋ค.
๋ถํ์ํ ๊ฐ์ฒด ์์ฑ์ ํผํ๋ ๊ฒ์ด ์ต์ ํ์ ๊ด์ ์์ ์ข๋ค.
JVM ์์๋ ํ๋์ ๊ฐ์ ๋จธ์ ์์ ๋์ผํ ๋ฌธ์์ด์ ์ฒ๋ฆฌํ๋ ์ฝ๋๊ฐ ์ฌ๋ฌ๊ฐ ์๋ค๋ฉด, ๊ธฐ์กด์ ๋ฌธ์์ด์ ์ฌ์ฌ์ฉ ํ๋ค.
val str1 = "Lorem ipsum dolor sit amet"
val str2 = "Lorem ipsum dolor sit amet"
println(str1 == str2) // true
println(str1 === str2) // true
Integer์ Long์ฒ๋ผ ๋ฐ์คํํ ๊ธฐ๋ณธ ์๋ฃํ๋ ์์ ๊ฒฝ์ฐ์๋ ์ฌ์ฌ์ฉ๋๋ค. (Int๋ -127 ~ 127 ๋ฒ์๋ฅผ ์บ์ํด ๋๋ค)
val num1: Int? = 1
val num2: Int? = 1
println(num1 == num2) // true
println(num1 === num2) // true
์ ์ฝ๋๋ Integer๊ฐ ์ฌ์ฌ์ฉ ๋๋ฏ๋ก, ===
๋ก ๋น๊ตํ์ ๋ true
๊ฐ ๋จ์ง๋ง
-128 ~ 127 ๋ฒ์๋ฅผ ๋ฒ์ด๋๋ ์ซ์๋ ์บ์๋์ง ์์ต๋๋ค.
val num3: Int? = 1234
val num4: Int? = 1234
println(num3 == num4) // true
println(num3 === num4) // false
nullable ํ์ ์ int ์๋ฃํ ๋์ Integer ์๋ฃํ ์ฌ์ฉ์ ๊ฐ์ ํ๊ฒ ๋๋ค.
๊ธฐ๋ณธ ์๋ฃํ์ null ์ผ ์ ์๊ณ , ํ์ ์๊ท๋จผํธ๋ก ์ฌ์ฉํ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
๊ฐ์ฒด ์์ฑ ๋น์ฉ์ ํญ์ ํด๊น?
๊ฐ์ฒด๋ฅผ ๋ฉ(Wrap) ํ๊ฒ ๋๋ฉด, ํฌ๊ฒ ์ธ๊ฐ์ง ๋น์ฉ์ด ๋ฐ์๋๋ค.
- ๊ฐ์ฒด๋ ๋ ๋ง์ ์ฉ๋์ ์ฐจ์งํ๋ค.
- ํค๋ ๋ฐ ๋ ํผ๋ฐ์ค๋ฅผ ์ํ ์ถ๊ฐ๊ณต๊ฐ์ด ํ์ํ๋ค.
- ์์๊ฐ ์บก์ํ ๋์ด ์๋ค๋ฉด, ์ ๊ทผ์ ์ถ๊ฐ์ ์ธ ํจ์ ํธ์ถ์ด ํ์ํ๋ค.
- ๊ฐ์ฒด๋ฅผ ์์ฑ์ ํ์์ง๋ง, ์ด๋ฅผ ์ฌ์ฌ์ฉํ๋ฉด ๋ถํ์ํ ๋น์ฉ์ ์ ๊ฑฐํ ์ ์๋ค.
๊ฐ์ฒด ์ ์ธ
๋งค ์๊ฐ ๊ฐ์ฒด๋ฅผ ์์ฑํ์ง ์๊ณ , ๊ฐ์ฒด๋ฅผ ์ฌ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ๊ฐ์ฒด์ ์ธ์ ์ฌ์ฉํ๋ ๊ฒ์ด๋ค.(์ฑ๊ธํค)
sealed class LinkedList<T>
class Node<T>(
val head: T,
val tail: ListedList<T>
): LinkedList<T>()
class Empty<T>: LinkedList<T>()
val list1: LinkedList<Int> = Node(1, Node(2, Empty()))
val list2: LinkedList<String> = Node("A", Node("B", Empty()))
์ ๊ตฌํ ์ฝ๋์์์ ๋ฌธ์ ์ ์ ๋ฆฌ์คํธ๋ฅผ ๋ง๋ค ๋๋ง๋ค Empty ์ธ์คํด์ค๋ฅผ ๋ง๋ค์ด์ผ ํ๋ค.
Empty ์ธ์คํด์ค๋ฅผ ํ๋๋ง ๋ง๋ค๊ณ , ๋ค๋ฅธ ๋ชจ๋ ๋ฆฌ์คํธ์์ ํ์ฉํ ์ ์๊ฒ ํ๋ค๋ฉด, ์ ๋ค๋ฆญ ํ์ ์ด ์ผ์น ํ์ง ์์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์๋ค.
์ด๋ฅผ ํด๊ฒฐํ๋ ค๋ฉด ๋ชจ๋ ํ์
์ ์๋ธํ์
์ธ Nothing
์ ์ด์ฉํ๋๊ฒ์ด๋ค.
sealed class LinkedList<T>
class Node<T>(
val head: T,
val tail: ListedList<T>
): LinkedList<T>()
class Empty<T>: LinkedList<Noting>()
val list1: LinkedList<Int> = Node(1, Node(2, Empty))
val list2: LinkedList<String> = Node("A", Node("B", Empty))
์บ์๋ฅผ ํ์ฉํ๋ ํฉํ ๋ฆฌ ํจ์
ํฉํ ๋ฆฌ ํจ์๋ ์บ์(cache)๋ฅผ ๊ฐ์ง ์ ์๋ค.
๊ทธ๋์ ํฉํ ๋ฆฌ ํจ์๋ ํญ์ ๊ฐ์ ๊ฐ์ฒด๋ฅผ ๋ฆฌํดํ๊ฒ ๋ง๋ค ์๋ ์๋ค.
์ค์ ๋ก stdlib
์ emptyList
๋ ์ด๋ฅผ ํ์ฉํด์ ๊ตฌํ๋์ด ์๋ค.
fun <T> List<T> emptyList() {
return EMPTY_LIST
}
์ฝํ๋ฆฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์๋ ๋ํดํธ ๋์คํจ์ณ์ธ Dispatchers.Default
๋ ์ฐ๋ ๋ ํ์ ๊ฐ๊ณ ์์ผ๋ฉฐ, ์ด๋ค ์ฒ๋ฆฌ๋ฅผ ์์ํ ๋ ์ฌ์ฉํ์ง ์๋ ์ฐ๋ ๋ ํ๋๋ฅผ ์ฌ์ฉํด ๋ช
๋ น์ ์ํํ๋ค.
์ฐธ๊ณ ๋ก ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ ๋น์ทํ ํํ๋ก ์ปค๋ฅ์ ํ์ ์ฌ์ฉํ๋ค.
๊ฐ์ฒด ์์ฑ์ด ๋ฌด๊ฒ๊ฑฐ๋ ์ฌ๋ฌ mutable ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํด์ผ ํ๋ ๊ฒฝ์ฐ์๋ ์ด์ฒ๋ผ ๊ฐ์ฒด ํ์ ์ฌ์ฉํ๋ ๊ฒ์ด ์ข๋ค.
๋ชจ๋ ์์ ํจ์๋ ๋ฉ๋ชจ์ด์ ์ด์ (memoization) ์ ํ์ฉํ์ฌ ์บ์ฑ์ ํ์ฉํ ์ ์๋ค.
๋ฉ๋ชจ์ด์ ์ด์ (Memoization)
์ด์ ์ ์ฐ์ฐ๋ ๊ฒฐ๊ณผ๋ฅผ ์ ์ฅํ๊ณ ์ฌ์ฉํ๋ ํจํด
๋ฉ๋ชจ๋ฆฌ ์์ ์์ ์ ์ฅ๊ฐ์ ์ ์ฅํ์ฌ ์ฌ์ฉํ ์ ์์ด ์๊ฐ ๋ณต์ก๋๋ฅผ ๋ง์ด ์ค์ธ๋ค
๋ฉ๋ชจ๋ฆฌ๊ฐ ํ์ํ ๋ ๊ฐ๋น์ง ์ปฌ๋ ํฐ(Garbage Collector, GC)๊ฐ ์๋์ผ๋ก ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํด์ ํด ์ฃผ๋ SoftReference๋ฅผ ์ฌ์ฉํ๋ฉด ๋ ์ข๋ค.
- WeakReference: ๊ฐ๋น์ง ์ปฌ๋ ํฐ๊ฐ ๊ฐ์ ์ ๋ฆฌํ๋ ๊ฒ์ ๋ง์ง ์๋๋ค. ๋ค๋ฅธ ๋ ํผ๋ฐ์ค๊ฐ ์ด๋ฅผ ์ฌ์ฉํ์ง ์์ผ๋ฉด ๊ณง๋ฐ๋ก ์ ๊ฑฐ๋๋ค.
- SoftReference: ๊ฐ๋น์ ์ปฌ๋ ํฐ๊ฐ ๊ฐ์ ์ ๋ฆฌํ ์ ์๊ณ , ์ ๋ฆฌํ์ง ์์์๋ ์๋ค. ๋ฉ๋ชจ๋ฆฌ๊ฐ ๋ถ์กฑํด์ ์ถ๊ฐ๋ก ํ์ํ ๊ฒฝ์ฐ์๋ง ์ ๋ฆฌํ๋ค.
์บ์๋ ์ธ์ ๋ ๋ฉ๋ชจ๋ฆฌ์ ์ฑ๋ฅ์ ํธ๋ ์ด๋ ์คํ๊ฐ ๋ฐ์ํ๋ฏ๋ก, ์บ์๋ฅผ ์ ์ค๊ณํ๋๊ฒ์ ์ฝ์ง ์๋ค.
์ฌ๋ฌ๊ฐ์ง ์ํฉ์ ์ ๊ณ ๋ คํ์ฌ ํ๋ช ํ๊ฒ ์ฌ์ฉํ๋๋ก ํ์.
๋ฌด๊ฑฐ์ด ๊ฐ์ฒด๋ฅผ ์ธ๋ถ ์ค์ฝํ๋ก ๋ณด๋ด๊ธฐ
์ฑ๋ฅ์ ์ํ ์ ์ฉํ ๋ฐฉ๋ฒ์ผ๋ก๋ ๋ฌด๊ฑฐ์ด ๊ฐ์ฒด๋ฅผ ์ธ๋ถ ์ค์ฝํ๋ก ๋ณด๋ด๋ ๋ฐฉ๋ฒ์ด ์๋ค.
Iterable ๋ด๋ถ์ ํ์ฅ ํจ์๋ฅผ ์ด์ฉํ์ฌ ์ต๋๊ฐ์ ๋ํ๋ด๋ max ๋ฅผ countMax ํจ์์ ๋ ๋ฒจ๋ก ์ฎ๊ฒผ๋ค.
fun <T: Comparable<T>> Iterable<T>.countMax(): Int {
val max = this.max()
return count = { it == max }
}
ํ์ฅ ๋ฆฌ์๋ฒ๋ก max ๋ฅผ ํธ์ถํ๋ ํํ๊ฐ ํ์คํ๊ฒ ๋ณด์ด๋ฏ๋ก ๊ฐ๋ ์ฑ์ด ํฅ์๋๋ค.
๋ฐ๋ณต ์ฒ๋ฆฌ์ค์ max ๊ฐ์ ํ๋ฒ๋ง ํ์ธํ๋ฏ๋ก ์ฝ๋์ ์ฑ๋ฅ์ด ์ข์์ง๋ค.
์ง์ฐ ์ด๊ธฐํ
๋ฌด๊ฑฐ์ด ํด๋์ค๋ฅผ ๋ง๋ค ๋ ์ง์ฐ๋๊ฒ ๋ง๋๋ ๊ฒ์ด ์ข๋ค.
ํ์ง๋ง ๋ฌด๊ฑฐ์ด ๊ฐ์ฒด๋ฅผ ๊ฐ์ก์ง๋ง ์๋ต์ ๋นจ๋ผ์ผ ํ๋ ๊ฒฝ์ฐ ์ข์ง ์๋ ์ผ์ด์ค๊ฐ ๋ ์ ์๋ค.
์ง์ฐ ์ด๊ธฐํ๋ ์ํฉ์ ๋ง๊ฒ ์ฌ์ฉํด์ผ ํ๋ค.
๊ธฐ๋ณธ ์๋ฃํ ์ฌ์ฉํ๊ธฐ
์ฝํ๋ฆฐ/JVM ์ปดํ์ผ๋ฌ์ ๋ด๋ถ์ ์ผ๋ก๋ ๊ธฐ๋ณธ ์๋ฃํ์ ์ฌ์ฉํ๋ค.
ํ์ง๋ง ๋ค์๊ณผ ๊ฐ์ ์ผ์ด์ค์์๋ ๊ธฐ๋ณธ ์๋ฃํ์ ๋ฉ(Wrap) ํ ์๋ฃํ์ ์ฌ์ฉํ๋ค.
- nullable ํ์ ์ ์ฐ์ฐํ ๋ (๊ธฐ๋ณธ ์๋ฃํ์ null ์ผ ์ ์๋ค.)
- ํ์ ์ ์ ๋ค๋ฆญ์ผ๋ก ์ฌ์ฉํ ๋
์ฝํ๋ฆฐ์ ์๋ฃํ | ์๋ฐ์ ์๋ฃํ |
---|---|
Int | int |
Int? | Integer |
List<Int> | List<Integer> |
์ซ์์ ๊ด๋ จ๋ ์ฐ์ฐ์ ์ด๋ค ํํ์ ์๋ฃํ์ ์ฌ์ฉํ๋ ์ฑ๋ฅ์ ์ผ๋ก ํฐ ์ฐจ์ด๋ ์๋ค.
๊ต์ฅํ ํฐ ์ปฌ๋ ์ ์ ์ฒ๋ฆฌํ ๋ ์ฐจ์ด๋ฅผ ํ์ธํ ์ ์๋ค.
๊ธฐ์กด ์ฝ๋์์ ์ฌ์ฉ๋๋ ์๋ฃํ์ ์ผ๊ด ๋ณ๊ฒฝํ๋ฉด, ์ฝ๋์ ๊ฐ๋ ์ฑ์ด ๋จ์ด์ง ์ ์๋ค.
์ ๋ฆฌ
๊ฐ์ฒด๋ฅผ ์์ฑํ ๋ ๋ฌธ์ ๋ฅผ ํผํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์ดํด๋ณด์๋ค.
๋ช๊ฐ์ง๋ ์ฝ๋์ ๊ฐ๋ ์ฑ์ ํฅ์์์ผ ์ฃผ๋ ์ฅ์ ๋ ์์ผ๋ฏ๋ก ์ ๊ทน์ ์ผ๋ก ์ฌ์ฉํ๋ ๊ฒ์ด ์ข๋ค.
Item 46 ํจ์ ํ์ ํ๋ผ๋ฏธํฐ๋ฅผ ๊ฐ๋ ํจ์์ inline ํ์ ์๋ฅผ ๋ถ์ฌ๋ผ
์ฝํ๋ฆฐ ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๊ณ ์ฐจ ํจ์(higher-order function)๋ฅผ ์ดํด๋ณด๋ฉด, ๋๋ถ๋ถ inline ํ์ ์๊ฐ ๋ถ์ด ์๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
inline fun repeat(times: Int, action: (Int) -> Unit) {
for (index in 0 until times) {
action(index)
}
}
repeat(10) {
println(it)
}
์ปดํ์ผ ์์ ์ ๋ค์๊ณผ ๊ฐ์ด ๋์ฒด๋๋ค.
for (index in 0 until times) {
println(index)
}
์ผ๋ฐ์ ์ธ ํจ์๋ฅผ ํธ์ถํ๋ฉด ํจ์ ๋ณธ๋ฌธ์ผ๋ก ์ ํํ๊ณ , ๋ณธ๋ฌธ์ ๋ชจ๋ ๋ฌธ์ฅ์ ํธ์ถํ ํ, ํจ์๋ฅผ ํธ์ถํ๋ ์์น๋ก ๋ค์ ์ ํํ๋ ๊ณผ์ ์ ๊ฑฐ์น๋ค.
inline
ํ์ ์๋ฅผ ์ฌ์ฉํ๋ฉด ๋ค์๊ณผ ๊ฐ์ ์ฅ์ ์ด ์๋ค.
- ํ์ ์๊ท๋จผํธ์ reified ํ์ ์๋ฅผ ๋ถ์ฌ์ ์ฌ์ฉํ ์ ์๋ค.
- ํจ์ ํ์ ํ๋ผ๋ฏธํฐ๋ฅผ ๊ฐ์ง ํจ์๊ฐ ํจ์ฌ ๋น ๋ฅด๊ฒ ๋์ํ๋ค.
- ๋น์ง์ญ(non-local) ๋ฆฌํด์ ์ฌ์ฉํ ์ ์๋ค.
ํ์ ์๊ท๋จผํธ๋ฅผ reified๋ก ์ฌ์ฉํ ์ ์๋ค.
reified ํ์ ์๋ฅผ ์ง์ ํ๋ฉด, ํ์ ํ๋ผ๋ฏธํฐ๋ฅผ ์ฌ์ฉํ ๋ถ๋ถ์ด ํ์ ์๊ท๋จผํธ๋ก ๋์ฒด๋๋ค.
inline fun <reified T> printTypeName() {
print(T::class.simpleName)
}
printTypeName<Int>() // Int
printTypeName<Char>() // Char
printTypeName<String>() // String
์ปดํ์ผ ํ๋ ๋์ printTypeName
์ ๋ณธ๋ฌธ์ด ๋ค์๊ณผ ๊ฐ์ด ๋์ฒด๋๋ค.
print(Int::class.simpleName) // Int
print(Char::class.simpleName) // Char
print(String::class.simpleName) // String
ํจ์ ํ์ ํ๋ผ๋ฏธํฐ๋ฅผ ๊ฐ์ง ํจ์๊ฐ ํจ์ฌ ๋น ๋ฅด๊ฒ ๋์ํ๋ค.
๋ชจ๋ ํจ์๋ inline ํ์ ์๋ฅผ ๋ถ์ด๋ฉด ์กฐ๊ธ๋ ๋น ๋ฅด๊ฒ ๋์ํ๋ค.
ํจ์ ํธ์ถ๊ณผ ๋ฆฌํด์ ์ํด ์ ํํ๋ ๊ณผ์ ๊ณผ ๋ฐฑ์คํ์ ์ถ์ ํ๋ ๊ณผ์ ์ด ์๊ธฐ ๋๋ฌธ์ด๋ค.
๊ทธ๋์ ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์๋ ๊ฐ๋จํ ํจ์๋ค์๋ ๋๋ถ๋ถ inline ํ์ ์๊ฐ ๋ถ์ด ์๋ค.
inline fun print(message: Any?) {
System.out.print(message)
}
์ฝํ๋ฆฐ/JVM ์์๋ JVM ์ต๋ช ํด๋์ค ๋๋ ์ผ๋ฐ ํด๋์ค๋ฅผ ๊ธฐ๋ฐ์ผ๋ก, ํจ์๋ฅผ ๊ฐ์ฒด๋ก ๋ง๋ค์ด ๋ธ๋ค.
val lambda: () -> Unit = {
// Codes
}
์์ ๊ฐ์ ๋๋ค ํํ์์ ํด๋์ค๋ก ์ปดํ์ผ ๋๋ค.
Function0(Unit) lambda = new Function0<Unit>() {
public Unit invoke() {
// Codes
}
}
๋ณ๋์ ํ์ผ์ ์ ์๋์ด ์๋ ์ผ๋ฐ ํด๋์ค๋ก ์ปดํ์ผํ๋ฉด, ๋ค์๊ณผ ๊ฐ๋ค.
public class Test$lambda implements Function0<Unit> {
public Unit invoke() {
// Codes
}
}
Function0 lambda = new Test$lambda()
๋ ๋ฐฉ์์ ํฐ ์ฐจ์ด๋ ์์ผ๋ฉฐ JVM ์์ ์๊ท๋จผํธ๊ฐ ์๋ ํจ์ํ์
์ Function0
ํ์
์ผ๋ก ๋ณํ๋๋ค.
() -> Unit
์Function0<Unit>
๋ก ์ปดํ์ผ() -> Int
์Function0<Int>
๋ก ์ปดํ์ผ(Int) -> Int
์Function0<Int, Int>
๋ก ์ปดํ์ผ(Int, Int) -> Int
์Function0<Int, Int, Int>
๋ก ์ปดํ์ผ
์ด๋ฌํ ๋ชจ๋ ์ธํฐํ์ด์ค๋ ๋ชจ๋ ์ฝํ๋ฆฐ ์ปดํ์ผ๋ฌ์ ์ํด ์์ฑ๋๋ค.
์์ฒญ์ด ์์๋ ์์ฑ๋๋ฏ๋ก, ๋ช ์์ ์ผ๋ก ์ฌ์ฉํ ์ ์์ผ๋ฉฐ, ๋์ ํจ์ํ์ ์ผ๋ก ์ฌ์ฉํ ์ ์๋ค.
๋น์ง์ญ์ ๋ฆฌํด(non-local return) ์ ์ฌ์ฉํ ์ ์๋ค.
fun repeatNoinline(times: Int, action: (Int) -> Unit) {
for (index in 0 until times) {
action(index)
}
}
repeatNoinline
์ ๋ด๋ถ์์ ๋ฆฌํด์ ์ฌ์ฉํ ์ ์๋ค.
fun main() {
repeatNninline(10) {
print(it)
return // ์ค๋ฅ: ํ์ฉ๋์ง ์๋๋ค.
}
}
์ด๋ ํจ์ ๋ฆฌํฐ๋ด์ด ์ปดํ์ผ๋ ๋, ํจ์๊ฐ ๊ฐ์ฒด๋ก ๋ํ๋์ด ๋ฐ์ํ๋ ๋ฌธ์ ์ด๋ค.
์ธ๋ผ์ธ์ด๋ผ๋ฉด ์ด๋ฌํ ์ ํ์ด ์๋ค. ํจ์๊ฐ main
ํจ์ ๋ด๋ถ์ ๋ฐํ๊ธฐ ๋๋ฌธ์ด๋ค.
fun main() {
repeat(10) {
print(it)
return // OK
}
}
๋๋ถ์ ์ ์ด๋ฌธ์ฒ๋ผ ๋ณด์ด๋ฉด์๋ ์ ๋์ํ๋ค.
fun getSomeMoney(): Money? {
repeat(100) {
val money = searchForMoney()
if (money != null) return money
}
return null
}
inline ํ์ ์์ ๋น์ฉ
inline
ํ์ ์๋ ์ ์ฉํ์ง๋ง ๋ชจ๋ ๊ณณ์ด ์ฌ์ฉํ ์ ์๋ค.
๋ํ์ ์ผ๋ก๋ ์ฌ๊ท์ ์ผ๋ก ๋์ํ ์ ์๋ค. ๋ง์ฝ ์ฌ๊ท๋ก ์ฌ์ฉํ๊ฒ ๋๋ฉด ๋ฌดํํ ๋์ฒด๋๋ ์ํฉ์ด ๋ฐ์ํ๋ฉฐ, ์ด๋ฌํ ์ค๋ฅ๋ฅผ IDE ์์ ์ก์์ค ์ ์์ด ๊ต์ฅํ ์ํํ๋ค.
inline ํ์ ์๋ฅผ ๋จ์ฉํ๋ฉด, ์ฝ๋์ ํฌ๋ฆฌ๊ฐ ์ฝ๊ฒ ์ปค์ง๋ค.
์๋ก ํธ์ถํ๋ ์ธ๋ผ์ธ ํจ์๊ฐ ๋ง์์ง๋ฉด ์ฝ๋๊ฐ ๊ธฐํ๊ธ์์ ์ผ๋ก ์ฆ๊ฐํ๋ฏ๋ก ์ํํ๋ค.
crossinline ๊ณผ oninline
ํจ์๋ฅผ ์ธ๋ผ์ธ์ผ๋ก ๋ง๋ค๊ณ ์ถ์ง๋ง, ์ด๋ค ์ด์ ๋ก ์ผ๋ถ ํจ์ ํ์ ํ๋ผ๋ฏธํฐ๋ inline์ผ๋ก ๋ฐ๊ณ ์ถ์ง ์๋ ๊ฒฝ์ฐ๊ฐ ์์ ์๋ ์๋ค.
- crossinline: ์๊ท๋จผํธ๋ก ์ธ๋ผ์ธ ํจ์๋ฅผ ๋ฐ์ง๋ง, ๋น์ง์ญ์ ๋ฆฌํด์ ํ๋ ํจ์๋ฅผ ๋ฐ์์ ์๊ฒ ๋ง๋ ๋ค. ์ธ๋ผ์ธ์ผ๋ก ๋ง๋ค์ง ์์ ๋ค๋ฅธ ๋๋ค ํํ์๊ณผ ์กฐํฉํด์ ์ฌ์ฉํ ๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ ๊ฒฝ์ฐ ํ์ฉํฉ๋๋ค.
- noinline: ์๊ท๋จผํธ๋ก ์ธ๋ผ์ธ ํจ์๋ฅผ ๋ฐ์ ์ ์๊ฒ ๋ง๋ ๋ค. ์ธ๋ผ์ธ ํจ์๊ฐ ์๋ ํจ์๋ฅผ ์๊ท๋จผํธ๋ก ์ฌ์ฉํ๊ณ ์ถ์ ๋ ํ์ฉํ๋ค.
๋คํ์ค๋ฝ๊ฒ๋ ๋ ํ์ ์์ ๋ํด์๋ IDE ์์ ์ ์ํด์ค๋ค. (๋์ถฉ ์๊ธฐ๋ง ํด๋ ๋๋คํจ)
์ ๋ฆฌ
์ธ๋ผ์ธ ํจ์๊ฐ ์ฌ์ฉ๋๋ ์ฃผ์ ์ฌ๋ก๋ฅผ ์ ๋ฆฌํด ๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
print
ํจ์์ฒ๋ผ ๋งค์ฐ ๋ง์ด ์ฌ์ฉ๋๋ ๊ฒฝ์ฐfilterIsInstance
ํจ์์ฒ๋ผ ํ์ ์๊ท๋จผํธ๋ก reified ํ์ ์ ์ ๋ฌ๋ฐ๋ ๊ฒฝ์ฐ- ํจ์ ํ์ ์ ํ๋ผ๋ฏธํฐ๋ฅผ ๊ฐ๋ ํฑ๋ ๋ฒจ ํฉ์๋ฅผ ์ ์ํด์ผ ํ๋ ๊ฒฝ์ฐ
API ๋ฅผ ์ ์ํ ๋ ์ธ๋ผ์ธ ํจ์๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ๋ ๊ฑฐ์ ์๋ค.
ํ ์ธ๋ผ์ธ ํจ์๊ฐ ๋ค๋ฅธ ์ธ๋ผ์ธ ํจ์๋ฅผ ํธ์ถํ๋ ๊ฒฝ์ฐ, ์ฝ๋๊ฐ ๊ธฐํ๊ธ์์ ์ผ๋ก ๋ง์์ง ์ ์์ผ๋ฏ๋ก ์ฃผ์ํ๋ผ
Item 47 ์ธ๋ผ์ธ ํด๋์ค์ ์ฌ์ฉ์ ๊ณ ๋ คํ๋ผ
์ธ๋ผ์ธ์ ํจ์ ๋ฟ๋ง์ด ์๋๋ผ, ํ๋์ ๊ฐ์ ๋ณด์ ํ๋ ๊ฐ์ฒด๋ ์ธ๋ผ์ธ์ผ๋ก ๋ง๋ค์ ์๋ค.
์ฝํ๋ฆฐ 1.3 ๋ถํฐ ๋์ ๋ ์ด ๊ธฐ๋ฅ์ ๊ธฐ๋ณธ ์์ฑ์ ํ๋กํผํฐ๊ฐ ํ๋์ธ ํด๋์ค ์์ inline ์ ๋ถ์ด๋ฉด, ํด๋น ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ๋ ์์น๊ฐ ๋ชจ๋ ํ๋กํผํฐ๋ก ๊ต์ฒด๋๋ค.
inline class Name(private val value: String)
์ด๋ฌํ inline ํด๋์ค๋ ํ์ ๋ง ๋ง๋ค๋ฉด, ๋ค์๊ณผ ๊ฐ์ด ๊ทธ๋ฅ ๊ฐ์ ๊ณง๋ฐ๋ก ์ง์ด๋ฃ๋ ๊ฒ๋ ํ์ฉ๋๋ค.
val name: Name = Name("Marcin")
// ์ปดํ์ผ๋ ๋ค์๊ณผ ๊ฐ์ ํํ๋ก ๋ฐ๋๋ค.
val name: String = "Marcin"
์ธ๋ผ์ธ ํด๋์ค๋ ๋ค๋ฅธ ์๋ฃํ์ ๋ํํด์ ์๋ก์ด ์๋ฃํ์ผ๋ก ๋ง๋ค ๋ ๋ง์ด ์ฌ์ฉ๋๋ค. ์ด๋ ์ด๋ ํ ์ค๋ฒ๋ ๋๋ ๋ฐ์ํ์ง ์๋๋ค (Item 45)
์ธ๋ผ์ธ ํด๋์ค๋ ๋ค์๊ณผ ๊ฐ์ ์ํฉ์์ ๋ง์ด ๋ฐ์ํ๋ค.
- ์ธก์ ๋จ์๋ฅผ ํํํ ๋
- ํ์ ์ค์ฉ์ผ๋ก ๋ฐ์ํ๋ ๋ฌธ์ ๋ฅผ ๋ง์ ๋
์ธก์ ๋จ์๋ฅผ ํํํ ๋
interface Timer {
fun callAfter(time: Int, callback: () -> Unit)
}
์ callAfter
ํจ์์ ํ๋ผ๋ฏธํฐ์ time ๋จ์๊ฐ ๋ถ๋ช
ํํ์ฌ ์คํด๊ฐ ์๊ธธ ์ ์๋ค.
์ด๋ฅผ ์ํด ํ๋ผ๋ฏธํฐ ์ด๋ฆ์ ์ธก์ ๋จ์๋ฅผ ๋ถ์ฌ์ฃผ๋๊ฒ์ด ๋ฌธ์ ํด๊ฒฐ์ ์ํ ๊ฐ์ฅ ์ฌ์ด ๋ฐฉ๋ฒ์ด๋ค.
interface Timer {
fun callAfter(timeMillis: Int, callback: () -> Unit)
}
๋ ์ข์ ๋ฐฉ๋ฒ์ ํ์ ์ ์ ํ์ ๊ฑฐ๋ ๊ฒ์ด๋ค.
inline class Minutes(val minutes: Int) {
fun toMillis(): Millis = Millis(minutes * 60 * 1000)
// ...
}
inline class Millis(val milliseconds: Int) {
// ...
}
interface User {
fun decideAboutTime(): Minutes
fun wakeUp()
}
interface Timer {
fun callAfter(timeMillis: Millis, callback: () -> Unit)
}
fun setUpUserWakeUpUser(user: User, timer: Timer) {
val time: Int = user.decideAboutTime()
timer.callAfter(time) { // ์ค๋ฅ: Type mismatch
user.wakeUp()
}
}
์๋์ ๊ฐ์ด ์ฌ๋ฐ๋ฅธ ํ์ ์ ๊ฐ์ ํ ์ ์๋ค.
fun setUpUserWakeUpUser(user: User, timer: Timer) {
val time: Int = user.decideAboutTime()
timer.callAfter(time.toMillis()) {
user.wakeUp()
}
}
๊ฐ์ฒด์์ฑ์ ์ํด ๋ฏธ๋ฆฌ ํ์ฅ ํ๋กํผํฐ๋ฅผ ๋ง๋ค์ด ๋์ด๋ ์ข๋ค.
inline val Int.min
get() = Minutes(this)
inline val Int.ms
get() = Millis(this)
val timeMin: Minutes = 10.min
ํ์ ์ค์ฉ์ผ๋ก ๋ฐ์ํ๋ ๋ฌธ์ ๋ฅผ ๋ง์ ๋
@Entity(tableName="grades")
classGrades(
@ColumnInfo(name = "studentId")
val studentId: Int,
@ColumnInfo(name = "teacherId")
val teacherId: Int,
@ColumnInfo(name = "schoolId")
val schoolId: Int,
// ...
)
๋ชจ๋ ID ๊ฐ Int ์๋ฃํ์ด๊ธฐ ๋๋ฌธ์, ์ค์๋ก ์๋ชป๋ ๊ฐ์ ๋ฃ์ ์ ์๋ค.
๋ค์๊ณผ ๊ฐ์ด Int ์๋ฃํ ๊ฐ์ inline ํด๋์ค๋ฅผ ํ์ฉํ์ฌ ๋ํํ์
inline class StudentId(val studentId: Int)
inline class TeachetId(val teacherId: Int)
inline class SchoolId(val schoolId: Int)
@Entity(tableName="grades")
classGrades(
@ColumnInfo(name = "studentId")
val studentId: Int,
@ColumnInfo(name = "teacherId")
val teacherId: Int,
@ColumnInfo(name = "schoolId")
val schoolId: Int,
// ...
)
์ธ๋ผ์ธ ํด๋์ค์ ์ธํฐํ์ด์ค
์ธ๋ผ์ธ ํด๋์ค์ ๋ง์ฐฌ๊ฐ์ง๋ก ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ ์ ์๋ค.
์ธํฐํ์ด์ค๋ฅผ ํตํด ํ์ ์ ๋ํ๋ด๋ ค๋ฉด, ๊ฐ์ฒด๋ฅผ ๋ํํด์ ์ฌ์ฉํด์ผ ํ๊ธฐ ๋๋ฌธ์ ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ๋ ์ธ๋ผ์ธ ํด๋์ค๋ ์๋ฌด๋ฐ ์๋ฏธ๊ฐ ์๋ค.
typealias
typealias ์ฌ์ฉํ๋ฉด, ํ์ ์ ์๋ก์ด ์ด๋ฆ์ ๋ถ์ฌ ์ค ์ ์๋ค.
์ ๋ฆฌ
์ธ๋ผ์ธ ํด๋์ค๋ฅผ ์ฌ์ฉํ๋ฉด ์ฑ๋ฅ์ ์ธ ์ค๋ฒํค๋ ์์ด ํ์ ์ ๋ํํ ์ ์๋ค.
์ธ๋ผ์ธ ํด๋์ค๋ ํ์ ์์คํ ์ ํตํด ์ค์๋ก ์ฝ๋๋ฅผ ์๋ชป ์์ฑํ๋ ๊ฒ์ ๋ง์์ฃผ๋ฏ๋ก, ์ฝ๋์ ์์ ์ฑ์ ํฅ์์์ผ์ค๋ค.
Item 48 ๋์ด์ ์ฌ์ฉํ์ง ์๋ ๊ฐ์ฒด์ ๋ ํผ๋ฐ์ค๋ฅผ ์ ๊ฑฐํ๋ผ
๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ๋ฅผ ์๋์ผ๋ก ํด์ฃผ๋ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด์ ์ต์ํ ๊ฐ๋ฐ์๋ ๊ฐ์ฒด ํด์ (free)๋ฅผ ๋ฐ๋ก ์๊ฐํ์ง ์๋๋ค.
๊ทธ๋ ๋ค๊ณ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ด๋ฆฌ๋ฅผ ์์ ํ ๋ฌด์ํด๋ฒ๋ฆฌ๋ฉด, ๋ฉ๋ชจ๋ฆฌ ๋์(๋ถํ์ํ ๋ฉ๋ชจ๋ฆฌ ์๋น)๊ฐ ๋ฐ์ํด์, ์ํฉ์ ๋ฐ๋ผ OOM(Out Of Memory Error)์ด ๋ฐ์ํ๊ธฐ๋ ํ๋ค.
๋ฐ๋ผ์ ๋ ์ด์ ์ฌ์ฉํ์ง ์๋ ๊ฐ์ฒด์ ๋ ํผ๋ฐ์ค๋ฅผ ์ ์งํ๋ฉด ์๋๋ค์ ๊ท์น์ ์ง์ผ์ฃผ๋ ๊ฒ์ด ์ข๋ค.
ํนํ ์ด๋ค ๊ฐ์ฒด๊ฐ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋ง์ด ์ฐจ์งํ๊ฑฐ๋, ์ธ์คํด์ค๊ฐ ๋ง์ด ์์ฑ๋ ๊ฒฝ์ฐ์๋ ๋ฐ๋์ ์ง์ผ์ค์ผ ํ๋ค.
์ํ๋ฅผ ์ ์งํ ๋๋ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ๋ฅผ ์ผ๋ํด ๋์ด์ผ ํ๋ค. ์ฝ๋๋ฅผ ์์ฑํ ๋๋ ๋ฉ๋ชจ๋ฆฌ์ ์ฑ๋ฅ ๋ฟ๋ง์ด ์๋๋ผ ๊ฐ๋ ์ฑ๊ณผ ํ์ฅ์ฑ์ ํญ์ ๊ณ ๋ คํด์ผ ํ๋ค.