{"componentChunkName":"component---src-containers-post-index-tsx","path":"/backend/kotlin-in-action/7장-널이_될_수_있는_값/","result":{"pageContext":{"next":{"id":"e580a327-c0c8-5aed-9e7e-6cff312d6912","html":"<h2 id=\"-61-컬렉션에-대한-함수형-api\" style=\"position:relative;\"><a href=\"#-61-%EC%BB%AC%EB%A0%89%EC%85%98%EC%97%90-%EB%8C%80%ED%95%9C-%ED%95%A8%EC%88%98%ED%98%95-api\" aria-label=\" 61 컬렉션에 대한 함수형 api permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 6.1 컬렉션에 대한 함수형 API</h2>\n<h3 id=\"-611-원소-제거와-변환-filter와-map\" style=\"position:relative;\"><a href=\"#-611-%EC%9B%90%EC%86%8C-%EC%A0%9C%EA%B1%B0%EC%99%80-%EB%B3%80%ED%99%98-filter%EC%99%80-map\" aria-label=\" 611 원소 제거와 변환 filter와 map permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 6.1.1 원소 제거와 변환: filter와 map</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">data class Person(val name: String, val age: Int)</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main() {\n    val list = listOf(1, 2, 3, 4)\n    println(list.filter { it % 2 == 0 })\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>filter 함수는 컬렉션을 순회하면서 주어진 람다가 true를 반환하는 원소들만 모은다.</li>\n<li>filter 함수는 주어진 술어와 일치하는 원소들로 이뤄진 새 컬렉션을 만들 수 있지만 그 과정에서 원소를 변환하지는 않는다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main() {\n    val list = listOf(1, 2, 3, 4)\n    println(list.map { it * it })\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>map은 입력 컬렉션의 원소를 변환할 수 있게 해준다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main() {\n    val numbers = listOf(1, 2, 3, 4, 5, 6, 7)\n    val filtered = numbers.filterIndexed { index, element -&gt; index % 2 == 0 &amp;&amp; element &gt; 3 }\n\n    println(filtered)\n\n    val mapped = numbers.mapIndexed { index, element -&gt; index + element }\n    println(mapped)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>index와 원소를 함께 제공</li>\n</ul>\n<h3 id=\"-612-컬렉션-값-누적-reduce와-fold\" style=\"position:relative;\"><a href=\"#-612-%EC%BB%AC%EB%A0%89%EC%85%98-%EA%B0%92-%EB%88%84%EC%A0%81-reduce%EC%99%80-fold\" aria-label=\" 612 컬렉션 값 누적 reduce와 fold permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 6.1.2 컬렉션 값 누적: reduce와 fold</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main() {\n    val list = listOf(1, 2, 3, 4, 5, 6, 7)\n    println(list.reduce { acc, element -&gt; acc + element })\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>reduce를 사용하면 컬렉션의 첫 번째 값을 누적기에 넣는다.\n<ul>\n<li>빈 컬렉션에 호출하면 안 된다.</li>\n</ul>\n</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main() {\n    val people = listOf(\n        Person(&quot;Alice&quot;, 29),\n        Person(&quot;Bob&quot;, 31),\n    )\n    val folded = people.fold(&quot;&quot;) { acc, person -&gt; acc + person.name }\n    println(folded)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>fold 함수는 reduce와 비슷하지만 첫 번째 원소를 누적 값으로 시작하는 대신, 임의의 시작 값을 선택할 수 있다.</li>\n<li><code>runningReduce</code>, <code>runningFold</code>를 사용하면 중간 단계의 모든 누적 값을 뽑아낼 수 있다.\n<ul>\n<li>반환객체는 리스트다.</li>\n</ul>\n</li>\n</ul>\n<h3 id=\"-613-컬렉션에-술어-적용-all-any-none-count-find\" style=\"position:relative;\"><a href=\"#-613-%EC%BB%AC%EB%A0%89%EC%85%98%EC%97%90-%EC%88%A0%EC%96%B4-%EC%A0%81%EC%9A%A9-all-any-none-count-find\" aria-label=\" 613 컬렉션에 술어 적용 all any none count find permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 6.1.3 컬렉션에 술어 적용: all, any, none, count, find</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">val canBeInClub27 = { p: Person -&gt; p.age &lt;= 27 }\n\nfun main() {\n    val people = listOf(\n        Person(&quot;Alice&quot;, 27),\n        Person(&quot;Bob&quot;, 31),\n    )\n    println(people.all(canBeInClub27))\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>all은 모든 원소가 술어를 만족시키는지 판단한다.</li>\n<li>any는 술어를 만족하는 원소가 하나라도 있는지 판단한다.</li>\n<li>none은 술어를 만족하는 원소가 없는지를 판단한다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">val canBeInClub27 = { p: Person -&gt; p.age &lt;= 27 }\n\nfun main() {\n    val people = listOf(\n        Person(&quot;Alice&quot;, 27),\n        Person(&quot;Bob&quot;, 31),\n    )\n    println(people.count(canBeInClub27))\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>술어를 만족하는 원소의 개수를 알고 싶다면 count를 사용한다.</li>\n<li>size보다는 count가 효율적이다.\n<ul>\n<li>count는 개수만 추적할 뿐 객체 생성하지 않음</li>\n</ul>\n</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">val canBeInClub27 = { p: Person -&gt; p.age &lt;= 27 }\n\nfun main() {\n    val people = listOf(\n        Person(&quot;Alice&quot;, 27),\n        Person(&quot;Bob&quot;, 31),\n    )\n    println(people.find(canBeInClub27))\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>술어를 만족하는 원소를 하나 찾고 싶으면 find 함수 사용</li>\n<li>원소가 전혀 없는 경우 null 반환</li>\n</ul>\n<h3 id=\"-614-리스트를-분할해-리스트의-쌍으로-만들기-partition\" style=\"position:relative;\"><a href=\"#-614-%EB%A6%AC%EC%8A%A4%ED%8A%B8%EB%A5%BC-%EB%B6%84%ED%95%A0%ED%95%B4-%EB%A6%AC%EC%8A%A4%ED%8A%B8%EC%9D%98-%EC%8C%8D%EC%9C%BC%EB%A1%9C-%EB%A7%8C%EB%93%A4%EA%B8%B0-partition\" aria-label=\" 614 리스트를 분할해 리스트의 쌍으로 만들기 partition permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 6.1.4 리스트를 분할해 리스트의 쌍으로 만들기: partition</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main() {\n    val people = listOf(\n        Person(&quot;Alice&quot;, 26),\n        Person(&quot;Bob&quot;, 29),\n        Person(&quot;Carol&quot;, 31),\n    )\n    val comeIn = people.filter(canBeInClub27)\n    val stayOut = people.filterNot(canBeInClub27)\n    println(comeIn)\n    println(stayOut)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>위 로직을 더 간결하게 처리할 수 있다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">    val (comeIn, stayOut) = people.partition(canBeInClub27)\n    println(comeIn)\n    println(stayOut)</code>\n        </deckgo-highlight-code>\n<ul>\n<li>partition 함수는 컬렉션을 술어를 만족하는 그룹과 만족하지 않는 그룹으로 나눈다.</li>\n</ul>\n<h3 id=\"-615-리스트를-여러-그룹으로-이뤄진-맵으로-바꾸기-groupby\" style=\"position:relative;\"><a href=\"#-615-%EB%A6%AC%EC%8A%A4%ED%8A%B8%EB%A5%BC-%EC%97%AC%EB%9F%AC-%EA%B7%B8%EB%A3%B9%EC%9C%BC%EB%A1%9C-%EC%9D%B4%EB%A4%84%EC%A7%84-%EB%A7%B5%EC%9C%BC%EB%A1%9C-%EB%B0%94%EA%BE%B8%EA%B8%B0-groupby\" aria-label=\" 615 리스트를 여러 그룹으로 이뤄진 맵으로 바꾸기 groupby permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 6.1.5 리스트를 여러 그룹으로 이뤄진 맵으로 바꾸기: groupBy</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main() {\n    val people = listOf(\n        Person(&quot;Alice&quot;, 31),\n        Person(&quot;Bob&quot;, 29),\n        Person(&quot;Carol&quot;, 31),\n    )\n    println(people.groupBy { it.age })\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>원소를 구분하는 특성이 키이고, 키 값에 따른 그룹을 생성한다.</li>\n</ul>\n<h3 id=\"-616-컬렉션을-맵으로-변환-associate-associatewith-associateby\" style=\"position:relative;\"><a href=\"#-616-%EC%BB%AC%EB%A0%89%EC%85%98%EC%9D%84-%EB%A7%B5%EC%9C%BC%EB%A1%9C-%EB%B3%80%ED%99%98-associate-associatewith-associateby\" aria-label=\" 616 컬렉션을 맵으로 변환 associate associatewith associateby permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 6.1.6 컬렉션을 맵으로 변환: associate, associateWith, associateBy</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main() {\n    val people = listOf(\n        Person(&quot;Joe&quot;, 22),\n        Person(&quot;Mary&quot;, 31),\n    )\n    val nameToAge = people.associate { it.name to it.age }\n    println(nameToAge)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>원소를 그룹화하지 않으면서 컬렉션으로부터 맵을 만들어내고 싶다면 <code>associate</code> 함수를 사용</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main() {\n    val people = listOf(\n        Person(&quot;Joe&quot;, 22),\n        Person(&quot;Mary&quot;, 31),\n        Person(&quot;Jamie&quot;, 22)\n    )\n    val personToAge = people.associateWith { it.age }\n    println(personToAge)\n    val ageToPerson = people.associateBy { it.age }\n    println(ageToPerson)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li><code>associateWith</code>는 컬렉션의 원래 원소를 키로 사용</li>\n<li><code>associateBy</code>는 컬렉션의 원래 원소를 맵의 값으로 하고, 람다가 만들어내는 값을 맵의 키로 사용</li>\n</ul>\n<h3 id=\"-617-가변-컬렉션의-원소-변경-replaceall-fill\" style=\"position:relative;\"><a href=\"#-617-%EA%B0%80%EB%B3%80-%EC%BB%AC%EB%A0%89%EC%85%98%EC%9D%98-%EC%9B%90%EC%86%8C-%EB%B3%80%EA%B2%BD-replaceall-fill\" aria-label=\" 617 가변 컬렉션의 원소 변경 replaceall fill permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 6.1.7 가변 컬렉션의 원소 변경: replaceAll, fill</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main() {\n    val names = mutableListOf(&quot;Martin&quot;, &quot;Samuel&quot;)\n    println(names)\n\n    names.replaceAll { it.uppercase() }\n    println(names)\n\n    names.fill(&quot;(redacted)&quot;)\n    println(names)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li><code>replaceAll</code>함수를 가변 컬렉션에 적용하면 지정한 람다로 모든 원소를 변경한다.</li>\n<li>가변 리스트의 모든 원소를 똑같은 값으로 바꾸는 경우에는 <code>fill</code>함수를 쓸 수 있다.</li>\n</ul>\n<h3 id=\"-618-컬렉션의-특별한-경우-처리-ifempty\" style=\"position:relative;\"><a href=\"#-618-%EC%BB%AC%EB%A0%89%EC%85%98%EC%9D%98-%ED%8A%B9%EB%B3%84%ED%95%9C-%EA%B2%BD%EC%9A%B0-%EC%B2%98%EB%A6%AC-ifempty\" aria-label=\" 618 컬렉션의 특별한 경우 처리 ifempty permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 6.1.8 컬렉션의 특별한 경우 처리: ifEmpty</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main() {\n    val empty = emptyList&lt;String&gt;()\n    val full = listOf(&quot;apple&quot;, &quot;orange&quot;, &quot;banana&quot;)\n    \n    println(empty.ifEmpty { listOf(&quot;no&quot;, &quot;values&quot;, &quot;here&quot;) })\n    println(full.ifEmpty { listOf(&quot;no&quot;, &quot;values&quot;, &quot;here&quot;) })\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li><code>ifEmpty</code> 함수를 사용화면 아무 원소도 없을 때 기본값을 생성하는 람다를 제공할 수 있다.</li>\n<li><code>ifBlank</code> 함수는 공백만 들어있는 문자열을 다룰 수 있다.</li>\n</ul>\n<h3 id=\"-619-컬렉션-나누기-chunked와-windowed\" style=\"position:relative;\"><a href=\"#-619-%EC%BB%AC%EB%A0%89%EC%85%98-%EB%82%98%EB%88%84%EA%B8%B0-chunked%EC%99%80-windowed\" aria-label=\" 619 컬렉션 나누기 chunked와 windowed permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 6.1.9 컬렉션 나누기: chunked와 windowed</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">val temperatures = listOf(27.7, 29.8, 22.0, 35.5, 19.1)</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main() {\n    println(temperatures.windowed(3))\n    //[[27.7, 29.8, 22.0], [29.8, 22.0, 35.5], [22.0, 35.5, 19.1]]\n    \n    println(temperatures.windowed(3) { it.sum() / it.size })\n    //[26.5, 29.099999999999998, 25.53333333333333]\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>슬라이딩 윈도우를 생성하고자 <code>windowed</code> 함수를 사용할 수 있다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main() {\n    println(temperatures.chunked(2))\n    // [[27.7, 29.8], [22.0, 35.5], [19.1]]\n    \n    println(temperatures.chunked(2) { it.sum() })\n    // [57.5, 57.5, 19.1]\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>컬렉션을 어떤 주어진 크기의 서로 겹치지 않는(서로소) 부분으로 나누고 싶을 때는 <code>chunked</code> 함수를 사용</li>\n</ul>\n<h3 id=\"-6110-컬렉션-합치기-zip\" style=\"position:relative;\"><a href=\"#-6110-%EC%BB%AC%EB%A0%89%EC%85%98-%ED%95%A9%EC%B9%98%EA%B8%B0-zip\" aria-label=\" 6110 컬렉션 합치기 zip permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 6.1.10 컬렉션 합치기: zip</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main() {\n    val names = listOf(&quot;Joe&quot;, &quot;Mary&quot;, &quot;Jamie&quot;)\n    val ages = listOf(22, 31, 22, 44, 0)\n    println(names.zip(ages))\n    // [(Joe, 22), (Mary, 31), (Jamie, 22)]\n    \n    println(names.zip(ages) { name, age -&gt; Person(name, age) })\n    // [Person(name=Joe, age=22), Person(name=Mary, age=31), Person(name=Jamie, age=22)]\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li><code>zip</code> 함수를 사용해 두 컬렉션에서 같은 인덱스에 있는 원소들의 쌍으로 이뤄진 리스트를 만들 수 있다.</li>\n<li>결과 컬렉션의 길이는 더 짧은 쪽의 길이와 같다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main() {\n    val countries = listOf(&quot;DE&quot;, &quot;NL&quot;, &quot;US&quot;)\n    println(names zip ages zip countries)\n    // [((Joe, 22), DE), ((Mary, 31), NL), ((Jamie, 22), US)]\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>중위 표기법을 쓸 수 있다.</li>\n<li>연쇄 호출이 가능하고, 리스트의 리스트가 되지는 않는다.</li>\n</ul>\n<h3 id=\"-6111-내포된-컬렉션의-원소-처리-flatmap과-flatten\" style=\"position:relative;\"><a href=\"#-6111-%EB%82%B4%ED%8F%AC%EB%90%9C-%EC%BB%AC%EB%A0%89%EC%85%98%EC%9D%98-%EC%9B%90%EC%86%8C-%EC%B2%98%EB%A6%AC-flatmap%EA%B3%BC-flatten\" aria-label=\" 6111 내포된 컬렉션의 원소 처리 flatmap과 flatten permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 6.1.11 내포된 컬렉션의 원소 처리: flatMap과 flatten</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class Book(val title: String, val authors: List&lt;String&gt;)\n\nval library = listOf(\n    Book(&quot;Kotlin in Action&quot;, listOf(&quot;Isakova&quot;, &quot;Elizarov&quot;, &quot;Aigner&quot;, &quot;Jemerov&quot;)),\n    Book(&quot;Atomic Kotlin&quot;, listOf(&quot;Eckel&quot;, &quot;Isakova&quot;)),\n    Book(&quot;The Three-Body Problem&quot;, listOf(&quot;Liu&quot;))\n)</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main() {\n    val authors = library.map { it.authors }\n    println(authors)\n    // [[Isakova, Elizarov, Aigner, Jemerov], [Eckel, Isakova], [Liu]]\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>내포된 컬렉션으로 반환된다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main() {\n    val authors = library.flatMap { it.authors }\n    println(authors)\n    // [Isakova, Elizarov, Aigner, Jemerov, Eckel, Isakova, Liu]\n    println(authors.toSet())\n    // [Isakova, Elizarov, Aigner, Jemerov, Eckel, Liu]\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li><code>flatMap</code> 함수는 컬렉션의 각 원소를 파라미터로 주어진 함수를 사용해 변환한다.</li>\n<li>변환한 결과를 하나의 리스트로 합친다.</li>\n<li>변환할 것이 없고 내포된 컬렉션을 평평한 컬렉션으로 만들고 싶다면 <code>flatten</code> 함수를 사용</li>\n</ul>\n<h2 id=\"-62-지연-계산-컬렉션-연산-시퀀스\" style=\"position:relative;\"><a href=\"#-62-%EC%A7%80%EC%97%B0-%EA%B3%84%EC%82%B0-%EC%BB%AC%EB%A0%89%EC%85%98-%EC%97%B0%EC%82%B0-%EC%8B%9C%ED%80%80%EC%8A%A4\" aria-label=\" 62 지연 계산 컬렉션 연산 시퀀스 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 6.2 지연 계산 컬렉션 연산: 시퀀스</h2>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">people.map(Person::name).filter { it.startsWith(&quot;A&quot;) }</code>\n        </deckgo-highlight-code>\n<ul>\n<li>위 함수는 리스트를 결국 2개를 만든다.</li>\n<li>원소가 수백만 개가 되면 효율이 떨어진다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">people\n    .asSequence()\n    .map(Person::name)\n    .filter { it.startsWith(&quot;A&quot;) }\n    .toList()</code>\n        </deckgo-highlight-code>\n<ul>\n<li>중간 결과를 저장하는 컬렉션이 생기지 않기 때문에 원소가 많은 경우 성능이 눈에 띄게 좋아진다.</li>\n<li>시퀀스의 원소는 필요할 때 lazy 계산이 된다.</li>\n</ul>\n<h3 id=\"-621-시퀀스-연산-실행-중간-연산과-최종-연산\" style=\"position:relative;\"><a href=\"#-621-%EC%8B%9C%ED%80%80%EC%8A%A4-%EC%97%B0%EC%82%B0-%EC%8B%A4%ED%96%89-%EC%A4%91%EA%B0%84-%EC%97%B0%EC%82%B0%EA%B3%BC-%EC%B5%9C%EC%A2%85-%EC%97%B0%EC%82%B0\" aria-label=\" 621 시퀀스 연산 실행 중간 연산과 최종 연산 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 6.2.1 시퀀스 연산 실행: 중간 연산과 최종 연산</h3>\n<ul>\n<li>중간 연산은 다른 시퀀스를 반환하고, 지연 계산된다.</li>\n<li>최종 연산은 결과를 반환한다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main() {\n    listOf(1, 2, 3, 4)\n        .asSequence()\n        .map {\n            print(&quot;map($it) &quot;)\n            it * it\n        }\n        .filter {\n            print(&quot;filter($it) &quot;)\n            it % 2 == 0\n        }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>이 코드는 아무 내용도 출력되지 않는다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main() {\n    listOf(1, 2, 3, 4)\n        .asSequence()\n        .map {\n            print(&quot;map($it) &quot;)\n            it * it\n        }\n        .filter {\n            print(&quot;filter($it) &quot;)\n            it % 2 == 0\n        }.toList()\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>최종 연산을 호출하면 연기됐던 모든 계산이 수행된다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main() {\n    println(\n        listOf(1, 2, 3, 4)\n            .asSequence()\n            .map { it * it }\n            .find { it &gt; 3 }\n    )\n    // 4\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>시퀀스에서 연산순서는 <strong>각 원소에 대해 순차적으로 적용</strong>된다.\n<ul>\n<li>원소에 연산을 차례대로 적용하다가 결과가 얻어지면 그 이후의 원소에 대해서는 변환이 이뤄지지 않을 수도 있다는 것</li>\n</ul>\n</li>\n<li>즉시 계산은 전체 컬렉션에 연산을 적용시키지만 지연 계산은 원소를 한번에 하나씩 처리한다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main() {\n    val people = listOf(\n        Person(&quot;Alice&quot;, 29), Person(&quot;Bob&quot;, 31),\n        Person(&quot;Charles&quot;, 31), Person(&quot;Dan&quot;, 21)\n    )\n    println(\n        people\n            .asSequence()\n            .map(Person::name)\n            .filter { it.length &lt; 4 }\n            .toList()\n    )\n    // [Bob, Dan]\n    println(\n        people\n            .asSequence()\n            .filter { it.name.length &lt; 4 }\n            .map(Person::name)\n            .toList())\n    // [Bob, Dan]\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>연쇄적인 연산에서 더 빨리 원소들을 제거하면 할수록 코드의 성능이 좋아진다.</li>\n</ul>\n<h3 id=\"-622-시퀀스-만들기\" style=\"position:relative;\"><a href=\"#-622-%EC%8B%9C%ED%80%80%EC%8A%A4-%EB%A7%8C%EB%93%A4%EA%B8%B0\" aria-label=\" 622 시퀀스 만들기 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 6.2.2 시퀀스 만들기</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main() {\n    val naturalNumbers = generateSequence(0) { it + 1 }\n    val numbersTo100 = naturalNumbers.takeWhile { it &lt;= 100 }\n    println(numbersTo100.sum())\n    // 5050\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li><code>generateSequence</code> 함수는 이전의 원소를 인자로 받아 다음 원소를 계산한다.</li>\n<li>위 변수는 모두 지연 계산된다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">import java.io.File\n\nfun File.isInsideHiddenDirectory() =\n    generateSequence(this) { it.parentFile }.any { it.isHidden }\n\nval file = File(&quot;/Users/svtk/.HiddenDir/a.txt&quot;)\nprintln(file.isInsideHiddenDirectory())\n// true\n</code>\n        </deckgo-highlight-code>\n<ul>\n<li>객체의 조상들로 이뤄진 시퀀스를 만드는 것도 시퀀스를 사용하는 방법이다.</li>\n</ul>","excerpt":"📖 6.1 컬렉션에 대한 함수형 API 🔖 6.1.1 원소 제거와 변환: filter와 map filter 함수는 컬렉션을 순회하면서 주어진 람다가 true를 반환하는 원소들만 모은다. filter 함수는 주어진 술어와 일치하는 원소들로 이뤄진 새 컬렉션을 만들 수 있지만 그 과정에서 원소를 변환하지는 않는다. map은 입력 컬렉션의 원소를 변환할 수 있게 해준다. index와 원소를 함께 제공 🔖 6.1.2 컬렉션 값 누적: reduce와 fold reduce…","fields":{"slug":"/backend/kotlin-in-action/6장-컬렉션과_시퀀스/"},"frontmatter":{"title":"Kotlin in Action - 6장 컬렉션과 시퀀스","thumbnail":{"childImageSharp":{"fluid":{"src":"/static/f7f7ddfa31d1614405dc5af1487b9ec4/9c94d/kotlin-in-action.png"}}},"draft":false,"category":"Back-End","tags":["Kotlin"],"date":"April 06, 2025"}},"previous":{"id":"551d6a82-918e-5d5b-a5da-34a62ef7491d","html":"<h2 id=\"-81-원시-타입과-기본-타입\" style=\"position:relative;\"><a href=\"#-81-%EC%9B%90%EC%8B%9C-%ED%83%80%EC%9E%85%EA%B3%BC-%EA%B8%B0%EB%B3%B8-%ED%83%80%EC%9E%85\" aria-label=\" 81 원시 타입과 기본 타입 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 8.1 원시 타입과 기본 타입</h2>\n<h3 id=\"-811-정수-부동소수점-수-문자-불리언-값을-원시-타입으로-표현\" style=\"position:relative;\"><a href=\"#-811-%EC%A0%95%EC%88%98-%EB%B6%80%EB%8F%99%EC%86%8C%EC%88%98%EC%A0%90-%EC%88%98-%EB%AC%B8%EC%9E%90-%EB%B6%88%EB%A6%AC%EC%96%B8-%EA%B0%92%EC%9D%84-%EC%9B%90%EC%8B%9C-%ED%83%80%EC%9E%85%EC%9C%BC%EB%A1%9C-%ED%91%9C%ED%98%84\" aria-label=\" 811 정수 부동소수점 수 문자 불리언 값을 원시 타입으로 표현 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 8.1.1 정수, 부동소수점 수, 문자, 불리언 값을 원시 타입으로 표현</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">val i: Int = 1\nval list: List&lt;Int&gt; = listOf(1, 2, 3)</code>\n        </deckgo-highlight-code>\n<ul>\n<li>코틀린은 원시 타입과 래퍼 타입을 구분하지 않는다.</li>\n<li>매번 객체로 표현하는 것이 아니라 실행 시점에 숫자 타입은 가능한 한 가장 효율적인 방식으로 표현된다.</li>\n</ul>\n<h3 id=\"-812-양수를-표현하기-위해-모든-비트-범위-사용-부호-없는-숫자-타입\" style=\"position:relative;\"><a href=\"#-812-%EC%96%91%EC%88%98%EB%A5%BC-%ED%91%9C%ED%98%84%ED%95%98%EA%B8%B0-%EC%9C%84%ED%95%B4-%EB%AA%A8%EB%93%A0-%EB%B9%84%ED%8A%B8-%EB%B2%94%EC%9C%84-%EC%82%AC%EC%9A%A9-%EB%B6%80%ED%98%B8-%EC%97%86%EB%8A%94-%EC%88%AB%EC%9E%90-%ED%83%80%EC%9E%85\" aria-label=\" 812 양수를 표현하기 위해 모든 비트 범위 사용 부호 없는 숫자 타입 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 8.1.2 양수를 표현하기 위해 모든 비트 범위 사용: 부호 없는 숫자 타입</h3>\n<table>\n<thead>\n<tr>\n<th>타입</th>\n<th>비트 크기</th>\n<th>표현 범위</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>UByte</code></td>\n<td>8비트</td>\n<td>0 ~ 255</td>\n</tr>\n<tr>\n<td><code>UShort</code></td>\n<td>16비트</td>\n<td>0 ~ 65,535</td>\n</tr>\n<tr>\n<td><code>UInt</code></td>\n<td>32비트</td>\n<td>0 ~ 4,294,967,295</td>\n</tr>\n<tr>\n<td><code>ULong</code></td>\n<td>64비트</td>\n<td>0 ~ 18,446,744,073,709,551,615</td>\n</tr>\n</tbody>\n</table>\n<ul>\n<li>코틀린에는 4가지 부호없는 타입이 있다.</li>\n<li>일반적인 원시 타입을 확장해 부호 없는 타입을 제공한다.</li>\n</ul>\n<h3 id=\"-813-널이-될-수-있는-기본-타입-int-boolean-등\" style=\"position:relative;\"><a href=\"#-813-%EB%84%90%EC%9D%B4-%EB%90%A0-%EC%88%98-%EC%9E%88%EB%8A%94-%EA%B8%B0%EB%B3%B8-%ED%83%80%EC%9E%85-int-boolean-%EB%93%B1\" aria-label=\" 813 널이 될 수 있는 기본 타입 int boolean 등 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 8.1.3 널이 될 수 있는 기본 타입: Int?, Boolean? 등</h3>\n<ul>\n<li>null 참조를 자바의 참조 타입의 변수에만 대입할 수 있기 때문에 널이 될 수 있는 코틀린 타입은 자바 원시 타입으로 표현할 수 없다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">data class Person(val name: String, val age: Int? = null) {\n    fun isOlderThan(other: Person): Boolean? {\n        if (age == null || other.age == null) {\n            return null\n        }\n        return age &gt; other.age\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>두 값이 널이 아닌지 검사해야 한다.</li>\n<li>컴파일러는 널 검사를 마친 다음에야 두 값을 일반적인 값처럼 다루도록 허용한다.</li>\n</ul>\n<h3 id=\"-814-수-변환\" style=\"position:relative;\"><a href=\"#-814-%EC%88%98-%EB%B3%80%ED%99%98\" aria-label=\" 814 수 변환 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 8.1.4 수 변환</h3>\n<ul>\n<li>코틀린과 자바의 가장 큰 차이점 중 하나는 수를 변환하는 방식이다.</li>\n<li>코틀린은 한 타입의 수를 다른 타입의 수로 자동 변환하지 않는다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">val i = 1\nval i: Long = b.toLong() // 자동 변환 X</code>\n        </deckgo-highlight-code>\n<ul>\n<li>모든 원시 타입에 대해 양방향 변환 함수가 모두 제공</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">val x = 1\nval list = listOf(1L, 2L, 3L)\nx in list // false</code>\n        </deckgo-highlight-code>\n<ul>\n<li>암시적 변환을 허용하지 않는다.</li>\n<li>숫자 리터럴을 상요할 때는 변환 함수를 호출할 필요가 없다.\n<ul>\n<li>ex) 1L, 0.2f</li>\n<li>컴파일러가 필요한 변환을 자동으로 넣어준다.</li>\n</ul>\n</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main() {\n    println(Int.MAX_VALUE + 1)\n    // 음수 최솟값\n    \n    println(Int.MIN_VALUE - 1)\n    // 양수 최댓값\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>코틀린 산술 연산자에서도 숫자 연산 시 오버플로나 언더플로가 발생할 수 있다.</li>\n<li>검사하느라 추가비용이 들지 않는다.</li>\n</ul>\n<h3 id=\"-815-any와-any-코틀린-타입-계층의-뿌리\" style=\"position:relative;\"><a href=\"#-815-any%EC%99%80-any-%EC%BD%94%ED%8B%80%EB%A6%B0-%ED%83%80%EC%9E%85-%EA%B3%84%EC%B8%B5%EC%9D%98-%EB%BF%8C%EB%A6%AC\" aria-label=\" 815 any와 any 코틀린 타입 계층의 뿌리 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 8.1.5 Any와 Any?: 코틀린 타입 계층의 뿌리</h3>\n<ul>\n<li>자바와 달리 Any가 원시 타입을 포함한 모든 타입의 조상 타입이다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">val answer: Any = 42</code>\n        </deckgo-highlight-code>\n<ul>\n<li>원시 타입 값을 Any 타입의 변수에 대입하면 자동으로 값을 객체로 감싼다.(박싱)</li>\n<li>Any가 널이 될 수 없는 타입임에 유의</li>\n</ul>\n<h3 id=\"-816-unit-타입-코틀린의-void\" style=\"position:relative;\"><a href=\"#-816-unit-%ED%83%80%EC%9E%85-%EC%BD%94%ED%8B%80%EB%A6%B0%EC%9D%98-void\" aria-label=\" 816 unit 타입 코틀린의 void permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 8.1.6 Unit 타입: 코틀린의 void</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun f(): Unit {}\nfun f() {}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>Unit을 반환하지만 타입을 지정할 필요는 없다.</li>\n<li>return을 명시할 필요가 없다.\n<ul>\n<li>컴파일러가 암시적으로 <code>return Unit</code>을 넣어준다.</li>\n</ul>\n</li>\n<li>함수형 프로그래밍에서 전통적으로 Unit은 <strong>단 하나의 인스턴스만 갖는 타입</strong>을 의미</li>\n<li>java의 void와 인스턴스의 유무가 가장 큰 차이</li>\n</ul>\n<h3 id=\"-817-nothing-타입-이-함수는-결코-반환되지-않는다\" style=\"position:relative;\"><a href=\"#-817-nothing-%ED%83%80%EC%9E%85-%EC%9D%B4-%ED%95%A8%EC%88%98%EB%8A%94-%EA%B2%B0%EC%BD%94-%EB%B0%98%ED%99%98%EB%90%98%EC%A7%80-%EC%95%8A%EB%8A%94%EB%8B%A4\" aria-label=\" 817 nothing 타입 이 함수는 결코 반환되지 않는다 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 8.1.7 Nothing 타입: 이 함수는 결코 반환되지 않는다</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun fail(message: String): Nothing {\n    throw IllegalArgumentException(message)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>Nothing 타입은 아무 값도 포함하지 않는다.</li>\n<li>함수의 반환 타입이나 반환 타입으로 쓰일 타입 파라미터로만 쓸 수 있다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">val address = company.address ?: fail(&quot;No address&quot;)</code>\n        </deckgo-highlight-code>\n<ul>\n<li>Nothing을 반환하는 함수를 엘비스 연산자의 오른쪽에 사용해서 전제조건을 검사할 수 있다.</li>\n</ul>\n<h2 id=\"-82-컬렉션과-배열\" style=\"position:relative;\"><a href=\"#-82-%EC%BB%AC%EB%A0%89%EC%85%98%EA%B3%BC-%EB%B0%B0%EC%97%B4\" aria-label=\" 82 컬렉션과 배열 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 8.2 컬렉션과 배열</h2>\n<h3 id=\"-821-널이-될-수-있는-값의-컬렉션과-널이-될-수-있는-컬렉션\" style=\"position:relative;\"><a href=\"#-821-%EB%84%90%EC%9D%B4-%EB%90%A0-%EC%88%98-%EC%9E%88%EB%8A%94-%EA%B0%92%EC%9D%98-%EC%BB%AC%EB%A0%89%EC%85%98%EA%B3%BC-%EB%84%90%EC%9D%B4-%EB%90%A0-%EC%88%98-%EC%9E%88%EB%8A%94-%EC%BB%AC%EB%A0%89%EC%85%98\" aria-label=\" 821 널이 될 수 있는 값의 컬렉션과 널이 될 수 있는 컬렉션 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 8.2.1 널이 될 수 있는 값의 컬렉션과 널이 될 수 있는 컬렉션</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun readNumbers(text: String): List&lt;Int?&gt; {\n    val result = mutableListOf&lt;Int?&gt;()\n    for (line in text.lineSequence()) {\n        val numberOrNull = line.toIntOrNull()\n        result.add(numberOrNull)\n    }\n    return result\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li><code>List&#x3C;Int?></code>\n<ul>\n<li>List 자체는 항상 Null이 아니다.</li>\n<li>각 원소는 Null이 될 수 있다.</li>\n</ul>\n</li>\n<li><code>List&#x3C;Int>?</code>\n<ul>\n<li>List는 Null이 될 수 있다.</li>\n<li>각 원소는 Null이 될 수 없다.</li>\n</ul>\n</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun readNumbers2(text: String): List&lt;Int?&gt; = text.lineSequence().map { it.toIntOrNull() }.toList()</code>\n        </deckgo-highlight-code>\n<ul>\n<li>함수형 프로그래밍으로 간단하게 표현할 수 있다.</li>\n<li>널이 될 수 있는 값으로 이뤄지고, 널이 될 수 있는 리스트를 정의해야 한다면 <code>List&#x3C;Int?>?</code>로 표현할 수 있다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">\nfun addValidNumbers(numbers: List&lt;Int?&gt;) {\n    var sumOfValidNumbers = 0\n    var invalidNumbers = 0\n    for (number in numbers) {\n        if (number != null) {\n            sumOfValidNumbers += number\n        } else {\n            invalidNumbers++\n        }\n    }\n    println(&quot;Sum of valid numbers: $sumOfValidNumbers&quot;)\n    println(&quot;Invalid numbers: $invalidNumbers&quot;)\n}\n\nfun main() {\n    val input = &quot;&quot;&quot;\n        1\n        abc\n        42\n    &quot;&quot;&quot;.trimIndent()\n    val numbers = readNumbers(input)\n    addValidNumbers(numbers)\n    // Sum of valid numbers: 43\n    // Invalid numbers: 1\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li><code>filterNotNull</code>을 사용해 간단하게 만들 수 있다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun addValidNumbers(numbers: List&lt;Int?&gt;) {\n    val validNumbers = numbers.filterNotNull()\n    println(&quot;Sum of valid numbers: ${validNumbers.sum()}&quot;)\n    println(&quot;Invalid numbers: ${numbers.size - validNumbers.size}&quot;)\n}</code>\n        </deckgo-highlight-code>\n<h3 id=\"-822-읽기-전용과-변경-가능한-컬렉션\" style=\"position:relative;\"><a href=\"#-822-%EC%9D%BD%EA%B8%B0-%EC%A0%84%EC%9A%A9%EA%B3%BC-%EB%B3%80%EA%B2%BD-%EA%B0%80%EB%8A%A5%ED%95%9C-%EC%BB%AC%EB%A0%89%EC%85%98\" aria-label=\" 822 읽기 전용과 변경 가능한 컬렉션 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 8.2.2 읽기 전용과 변경 가능한 컬렉션</h3>\n<p>코틀린의 컬렉션 인터페이스는 읽기 전용(read-only) 과 변경 가능(mutable) 두 가지 버전이 있다.</p>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun &lt;T&gt; copyElements(source: Collection&lt;T&gt;, target: MutableCollection&lt;T&gt;) {\n    for (item in source) {\n        target.add(item)\n    }\n}</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun &lt;T&gt; copyElements(source: Collection&lt;T&gt;, target: MutableCollection&lt;T&gt;) {\n    for (item in source) {\n        target.add(item)\n    }\n}\n\nfun main() {\n    val source: Collection&lt;Int&gt; = arrayListOf(3, 5, 7)\n    val target: Collection&lt;Int&gt; = arrayListOf(1)\n    copyElements(source, target) // 컴파일 에러 발생\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>읽기 전용 컬렉션이 항상 thread safe하지는 않는다.\n<ul>\n<li>내부에서 변경할 수도 있음!</li>\n<li>즉, 불변은 아니다.</li>\n</ul>\n</li>\n</ul>\n<h3 id=\"-823-코틀린-컬렉션과-자바-컬렉션은-밀접히-연관됨\" style=\"position:relative;\"><a href=\"#-823-%EC%BD%94%ED%8B%80%EB%A6%B0-%EC%BB%AC%EB%A0%89%EC%85%98%EA%B3%BC-%EC%9E%90%EB%B0%94-%EC%BB%AC%EB%A0%89%EC%85%98%EC%9D%80-%EB%B0%80%EC%A0%91%ED%9E%88-%EC%97%B0%EA%B4%80%EB%90%A8\" aria-label=\" 823 코틀린 컬렉션과 자바 컬렉션은 밀접히 연관됨 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 8.2.3 코틀린 컬렉션과 자바 컬렉션은 밀접히 연관됨</h3>\n<p>모든 코틀린 컬렉션은 그에 상응하는 자바 컬렉션 인터페이스의 인스턴스이다.</p>\n<ul>\n<li>코틀린의 읽기 전용과 변경 가능 인터페이스의 기본 구조는 <code>java.util</code> 패키지에 있는 자바 컬렉션 인터페이스의 구조와 같다.</li>\n<li>읽기 전용 인터페이스에는 컬렉션을 변경할 수 있는 모든 요소가 빠져있다.</li>\n</ul>\n<table>\n<thead>\n<tr>\n<th>컬렉션 타입</th>\n<th>읽기 전용 타입</th>\n<th>변경 가능 타입</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>List</code></td>\n<td><code>listOf</code>, <code>List</code></td>\n<td><code>mutableListOf</code>, <code>MutableList</code></td>\n</tr>\n<tr>\n<td><code>Set</code></td>\n<td><code>setOf</code></td>\n<td><code>mutableSetOf</code>, <code>MutableSet</code> 등</td>\n</tr>\n<tr>\n<td><code>Map</code></td>\n<td><code>mapOf</code></td>\n<td><code>mutableMapOf</code>, <code>MutableMap</code> 등</td>\n</tr>\n</tbody>\n</table>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">public class CollectionUtils {\n    public static List&lt;String&gt; upperCaseAll(List&lt;String&gt; items) {\n        for (int i = 0; i &lt; items.size(); i++) {\n             items.set(i, items.get(i).toUpperCase());\n        }\n        return items;\n    }\n}</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun printInUpperCase(list: List&lt;String&gt;) {\n    println(CollectionUtils.upperCaseAll(list))\n    println(list.first())\n}\n\nfun main() {\n    val list = listOf(&quot;a&quot;, &quot;b&quot;, &quot;c&quot;)\n    printInUpperCase(list)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>컬렉션을 변경하는 자바 메서드에게 읽기 전용 <code>Collection</code>을 넘겨도 코틀린 컴파일러가 이를 막을 수 없다.</li>\n<li>컬렉션을 자바 코드에게 넘길 때는 특별히 주의를 기울여야 한다.</li>\n</ul>\n<h3 id=\"-824-자바에서-선언한-컬렉션은-코틀린에서-플랫폼-타입으로-보임\" style=\"position:relative;\"><a href=\"#-824-%EC%9E%90%EB%B0%94%EC%97%90%EC%84%9C-%EC%84%A0%EC%96%B8%ED%95%9C-%EC%BB%AC%EB%A0%89%EC%85%98%EC%9D%80-%EC%BD%94%ED%8B%80%EB%A6%B0%EC%97%90%EC%84%9C-%ED%94%8C%EB%9E%AB%ED%8F%BC-%ED%83%80%EC%9E%85%EC%9C%BC%EB%A1%9C-%EB%B3%B4%EC%9E%84\" aria-label=\" 824 자바에서 선언한 컬렉션은 코틀린에서 플랫폼 타입으로 보임 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 8.2.4 자바에서 선언한 컬렉션은 코틀린에서 플랫폼 타입으로 보임</h3>\n<ul>\n<li>플랫폼 타입의 경우 코틀린 쪽에는 널 관련 정보가 없다.</li>\n<li>자바 쪽에서 선언한 컬렉션 타입의 변수를 코틀린에서는 플랫폼 타입으로 본다.</li>\n<li>컬렉션 타입이 시그니처에 들어간 자바 메서드 구현을 오버라이드하려는 경우 읽기 전용 컬렉션과 변경 가능 컬렉션의 차이가 문제가 된다.\n<ul>\n<li>컬렉션이 null이 될 수 있는가?</li>\n<li>컬렉션의 원소가 null이 될 수 있는가?</li>\n<li>여러번이 작성할 메서드가 컬렉션을 변경할 수 있는가?</li>\n</ul>\n</li>\n</ul>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">public interface FileContentProcessor {\n    void processContents(File path, byte[] binaryContents, List&lt;String&gt; textContents);\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>이를 코틀린으로 구현하면 아래와 같다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class FileIndexer : FileContentProcessor {\n    override fun processContents(path: File, binaryContents: ByteArray?, textContents: MutableList&lt;String&gt;?) {\n        TODO(&quot;Not yet implemented&quot;)\n    }\n}</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">interface DataParser&lt;T&gt; {\n    void parseData(\n            String input,\n            List&lt;T&gt; output,\n            List&lt;String&gt; errors\n    );\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>이를 코틀린으로 구현하면 아래와 같다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class PersonParser : DataParser&lt;Person&gt; {\n    override fun parseData(input: String, output: MutableList&lt;Person&gt;, errors: MutableList&lt;String?&gt;) {\n        TODO(&quot;Not yet implemented&quot;)\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>java 인터페이스나 클래스가 어떤 맥락에서 사용되는지 정확히 알아야 한다.</li>\n</ul>\n<h3 id=\"-825-성능과-상호운용을-위해-객체의-배열이나-원시-타입의-배열을-만들기\" style=\"position:relative;\"><a href=\"#-825-%EC%84%B1%EB%8A%A5%EA%B3%BC-%EC%83%81%ED%98%B8%EC%9A%B4%EC%9A%A9%EC%9D%84-%EC%9C%84%ED%95%B4-%EA%B0%9D%EC%B2%B4%EC%9D%98-%EB%B0%B0%EC%97%B4%EC%9D%B4%EB%82%98-%EC%9B%90%EC%8B%9C-%ED%83%80%EC%9E%85%EC%9D%98-%EB%B0%B0%EC%97%B4%EC%9D%84-%EB%A7%8C%EB%93%A4%EA%B8%B0\" aria-label=\" 825 성능과 상호운용을 위해 객체의 배열이나 원시 타입의 배열을 만들기 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 8.2.5 성능과 상호운용을 위해 객체의 배열이나 원시 타입의 배열을 만들기</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main(args: Array&lt;String&gt;) {\n    for (i in args.indices) {\n        println(&quot;Argument $i is: ${args[i]}&quot;)\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>코틀린 배열은 타입 파라미터를 받는 클래스다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main() {\n    val letters = Array&lt;String&gt;(26) { i -&gt; (&#39;a&#39; + i).toString() }\n    println(letters.joinToString(&quot;&quot;))\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>타입인자를 생략해도 컴파일러가 알아서 원소 타입을 추론해준다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main() {\n    val letters = Array(26) { i -&gt; (&#39;a&#39; + i).toString() }\n    println(letters.joinToString(&quot;&quot;))\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>데이터가 이미 컬렉션에 들어 있다면 컬렉션을 배열로 변환해야 한다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main() {\n    val strings = listOf(&quot;a&quot;, &quot;b&quot;, &quot;c&quot;)\n    println(&quot;%s/%s/%s&quot;.format(*strings.toTypedArray())) // 스프레드 연산자 사용\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>코틀린은 원시 타입의 배열을 표현하는 별도 클래스를 각 원시 타입마다 하나씩 제공한다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">val fiveZeros = IntArray(5)\nval fiveZerosToo = intArrayOf(0, 0, 0, 0, 0)\n\nfun main() {\n    val squares = IntArray(5) { i -&gt; (i + 1) * (i + 1) }\n    println(squares.joinToString())\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>배열을 만드는 방법은 다양하다.</li>\n</ul>","excerpt":"📖 8.1 원시 타입과 기본 타입 🔖 8.1.1 정수, 부동소수점 수, 문자, 불리언 값을 원시 타입으로 표현 코틀린은 원시 타입과 래퍼 타입을 구분하지 않는다. 매번 객체로 표현하는 것이 아니라 실행 시점에 숫자 타입은 가능한 한 가장 효율적인 방식으로 표현된다. 🔖 8.1.2 양수를 표현하기 위해 모든 비트 범위 사용: 부호 없는 숫자 타입 타입 비트 크기 표현 범위 UByte 8비트 0 ~ 255 UShort 16비트 0 ~ 65,535 UInt 32비트 0 ~ 4,294,967,29…","fields":{"slug":"/backend/kotlin-in-action/8장-기본_타입_컬렉션_배열/"},"frontmatter":{"title":"Kotlin in Action - 8장 기본 타입, 컬렉션, 배열","thumbnail":{"childImageSharp":{"fluid":{"src":"/static/f7f7ddfa31d1614405dc5af1487b9ec4/9c94d/kotlin-in-action.png"}}},"draft":false,"category":"Back-End","tags":["Kotlin"],"date":"April 20, 2025"}},"node":{"id":"e6422292-3901-5f36-bb54-df3880644ca6","html":"<h2 id=\"-71-nullpointerexception을-피하고-값이-없는-경우-처리-널-가능성\" style=\"position:relative;\"><a href=\"#-71-nullpointerexception%EC%9D%84-%ED%94%BC%ED%95%98%EA%B3%A0-%EA%B0%92%EC%9D%B4-%EC%97%86%EB%8A%94-%EA%B2%BD%EC%9A%B0-%EC%B2%98%EB%A6%AC-%EB%84%90-%EA%B0%80%EB%8A%A5%EC%84%B1\" aria-label=\" 71 nullpointerexception을 피하고 값이 없는 경우 처리 널 가능성 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 7.1 NullPointerException을 피하고 값이 없는 경우 처리: 널 가능성</h2>\n<ul>\n<li>코틀린을 포함한 최신 언어에서 null에 대한 접근 방법은 가능한 이 문제를 실행 시점에서 컴파일 시점으로 옮기는 것</li>\n<li>널이 될 수 있는지 여부를 타입 시스템에 추가하으로써 컴파일러가 여러 가지 오류를 컴파일 시 미리 감지해서 실행 시점에 발생할 수 있는 예외의 가능성을 줄일 수 있다.</li>\n</ul>\n<h2 id=\"-72-널이-될-수-있는-타입으로-널이-될-수-있는-변수-명시\" style=\"position:relative;\"><a href=\"#-72-%EB%84%90%EC%9D%B4-%EB%90%A0-%EC%88%98-%EC%9E%88%EB%8A%94-%ED%83%80%EC%9E%85%EC%9C%BC%EB%A1%9C-%EB%84%90%EC%9D%B4-%EB%90%A0-%EC%88%98-%EC%9E%88%EB%8A%94-%EB%B3%80%EC%88%98-%EB%AA%85%EC%8B%9C\" aria-label=\" 72 널이 될 수 있는 타입으로 널이 될 수 있는 변수 명시 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 7.2 널이 될 수 있는 타입으로 널이 될 수 있는 변수 명시</h2>\n<ul>\n<li>코틀린과 자바의 첫 번째이자 가장 중요한 차이는 코틀린 타입 시스템이 널이 될 수 있는 타입을 명시적으로 지원한다는 점이다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun strLen(s: String) = s.length</code>\n        </deckgo-highlight-code>\n<ul>\n<li>null이 인자로 들어올 수 없다면 위와 같이 정의 가능</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main() {\n    strLen(null) // error\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>컴파일 시, 오류가 발생한다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun strLenSafe(s: String?) = s.length() // error</code>\n        </deckgo-highlight-code>\n<ul>\n<li>타입 이름 뒤에 물음표를 붙이면 그 타입의 변수나 프로퍼티에 null 참조를 저장할 수 있다.</li>\n<li>널이 될 수 있는 타입 값의 메서드를 직접 호출할 수는 없다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main() {\n    val x: String? = null\n    var y: String = x // error\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>널이 될 수 있는 값을 널이 될 수 없는 타입의 변수에 대입할 수 없다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main() {\n    val x: String? = null\n    strLen(x) // error\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>널이 될 수 있는 타입의 값을 null이 아닌 타입의 파라미터를 받는 함수에 전달할 수 없다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun strLenSafe(s: String?): Int = if (s != null) s.length else 0</code>\n        </deckgo-highlight-code>\n<ul>\n<li>null과 비교하고 나면 컴파일러는 그 사실을 기억하고 null이 아님이 확실한 영역에서는 해당 값을 null이 아닌 타입의 값처럼 사용할 수 있다.</li>\n</ul>\n<h2 id=\"-73-타입의-의미-자세히-살펴보기\" style=\"position:relative;\"><a href=\"#-73-%ED%83%80%EC%9E%85%EC%9D%98-%EC%9D%98%EB%AF%B8-%EC%9E%90%EC%84%B8%ED%9E%88-%EC%82%B4%ED%8E%B4%EB%B3%B4%EA%B8%B0\" aria-label=\" 73 타입의 의미 자세히 살펴보기 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 7.3 타입의 의미 자세히 살펴보기</h2>\n<ul>\n<li>타입\n<ul>\n<li>가능한 값의 집합과 그런 값들에 대해 수행할 수 있는 연산의 집합</li>\n</ul>\n</li>\n<li>자바의 타입 시스템은 null을 제대로 다루지 못한다.\n<ul>\n<li>ex. String 타입의 변수에는 null, String 모두 들어갈 수 있지만 완전히 다르다. 심지어, instanceof 연산자도 null이 String이 아니라고 답한다.</li>\n</ul>\n</li>\n<li>코틀린의 널이 될 수 있는 타입은 이런 문제에 대해 종합적인 해법을 제공한다.</li>\n</ul>\n<h2 id=\"-74-안전한-호출-연산자로-null-검사와-메서드-호출-합치기-\" style=\"position:relative;\"><a href=\"#-74-%EC%95%88%EC%A0%84%ED%95%9C-%ED%98%B8%EC%B6%9C-%EC%97%B0%EC%82%B0%EC%9E%90%EB%A1%9C-null-%EA%B2%80%EC%82%AC%EC%99%80-%EB%A9%94%EC%84%9C%EB%93%9C-%ED%98%B8%EC%B6%9C-%ED%95%A9%EC%B9%98%EA%B8%B0-\" aria-label=\" 74 안전한 호출 연산자로 null 검사와 메서드 호출 합치기  permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 7.4 안전한 호출 연산자로 null 검사와 메서드 호출 합치기: ?.</h2>\n<ul>\n<li><code>?.</code>는 null 검사와 메서드 호출을 한 연산으로 수행</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class Employee(val name: String, val manager: Employee?)\n\nfun managerName(employee: Employee): String? = employee.manager?.name\n\nfun main() {\n    val ceo = Employee(&quot;Da Boss&quot;, null)\n    val developer = Employee(&quot;Bob Smith&quot;, ceo)\n    println(managerName(developer))\n    println(managerName(ceo))\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>Employee로 프로퍼티 접근 시 안전한 호출을 사용하는 방법</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class Address(val streetAddress: String, val zipCode: Int, val city: String, val country: String)\n\nclass Company(val name: String, val address: Address?)\n\nclass Person(val name: String, val company: Company?)\n\nfun Person.countryName(): String {\n    val country = this.company?.address?.country\n    return if (country != null) country else &quot;Unknown&quot;\n}\n\nfun main() {\n    val person = Person(&quot;Dmitry&quot;, null)\n    println(person.countryName())\n    // Unknown\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>null 검사를 한줄로 연쇄적으로 할 수 있다!</li>\n</ul>\n<h2 id=\"-75-엘비스-연산자로-null에-대한-기본값-제공-\" style=\"position:relative;\"><a href=\"#-75-%EC%97%98%EB%B9%84%EC%8A%A4-%EC%97%B0%EC%82%B0%EC%9E%90%EB%A1%9C-null%EC%97%90-%EB%8C%80%ED%95%9C-%EA%B8%B0%EB%B3%B8%EA%B0%92-%EC%A0%9C%EA%B3%B5-\" aria-label=\" 75 엘비스 연산자로 null에 대한 기본값 제공  permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 7.5 엘비스 연산자로 null에 대한 기본값 제공: ?:</h2>\n<ul>\n<li>엘비스 연산자\n<ul>\n<li>null 대신 사용할 기본값을 지정할 때 편리하게 사용할 수 있는 연산자</li>\n<li>null 복합 연산자라고도 부름</li>\n</ul>\n</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun greet(name: String?) {\n    val recipient: String = name ?: &quot;unnamed&quot;\n    println(&quot;Hello, $recipient&quot;)\n}</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun strLenSafe(s: String?): Int = s?.length ?: 0</code>\n        </deckgo-highlight-code>\n<ul>\n<li>한줄로 줄여쓸 수 있다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class Address(val streetAddress: String, val zipCode: Int, val city: String, val country: String)\n\nclass Company(val name: String, val address: Address?)\n\nclass Person(val name: String, val company: Company?)\n\nfun printShippingLabel(person: Person) {\n    val address = person.company?.address\n        ?: throw IllegalArgumentException(&quot;No address&quot;)\n    with(address) {\n        println(streetAddress)\n        println(&quot;$zipCode $city, $country&quot;)\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>코드가 매우 간결해진다!</li>\n</ul>\n<h2 id=\"-76-예외를-발생시키지-않고-안전하게-타입을-캐스트하기-as\" style=\"position:relative;\"><a href=\"#-76-%EC%98%88%EC%99%B8%EB%A5%BC-%EB%B0%9C%EC%83%9D%EC%8B%9C%ED%82%A4%EC%A7%80-%EC%95%8A%EA%B3%A0-%EC%95%88%EC%A0%84%ED%95%98%EA%B2%8C-%ED%83%80%EC%9E%85%EC%9D%84-%EC%BA%90%EC%8A%A4%ED%8A%B8%ED%95%98%EA%B8%B0-as\" aria-label=\" 76 예외를 발생시키지 않고 안전하게 타입을 캐스트하기 as permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 7.6 예외를 발생시키지 않고 안전하게 타입을 캐스트하기: as?</h2>\n<ul>\n<li>코틀린에서 대상 값을 as로 지정한 타입으로 바꿀 수 없으면 <code>ClassCastException</code>이 발생</li>\n<li>as를 사용할 때마다 is로 변환 가능한 타입인지 검사할 수 있지만 너무 귀찮다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class Person(val firstName: String, val lastName: String) {\n    override fun equals(o: Any?): Boolean {\n        val otherPerson = o as? Person ?: return false\n\n        return otherPerson.firstName == firstName &amp;&amp; otherPerson.lastName == lastName\n    }\n\n    override fun hashCode(): Int = firstName.hashCode() * 37 + lastName.hashCode()\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>as? 연산자는 어떤 값을 지정한 타입으로 변환한다. 변활할 수 없으면 null을 반환한다.</li>\n<li>하나의 식으로 해결 가능해진다.</li>\n</ul>\n<h2 id=\"-77-널-아님-단언-\" style=\"position:relative;\"><a href=\"#-77-%EB%84%90-%EC%95%84%EB%8B%98-%EB%8B%A8%EC%96%B8-\" aria-label=\" 77 널 아님 단언  permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 7.7 널 아님 단언: !!</h2>\n<ul>\n<li>널 아님 단언은 코틀린에서 널이 될 수 있는 타입의 값을 다룰 때 사용할 수 있는 도구 중에서 가장 단순하면서도 무딘 도구다.</li>\n<li><code>!!</code>을 사용하면 어떤 값이든 널이 아닌 타입으로 바꿀 수 있다.</li>\n<li>null에 대해 <code>!!</code>를 사용하면 NPE 발생</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun ignoreNulls(str: String?) {\n    val strNotNull: String = str!! // 예외는 이 지점을 가리킨다.\n    println(strNotNull.length)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>예외가 가리키는 지점은 단언문이 위치한 곳을 가리킨다.</li>\n<li>결국 <code>!!</code>는 컴파일러에게 null이 아님을 알고 있으며, 예외가 발생해도 감수하겠다는 것을 말하는 것이다.</li>\n<li>굳이 느낌표 두개를 선택한 것은 더 나은 방법을 찾아보라는 코틀린 설계자들의 의도이다.\n<ul>\n<li>기호가 못생기고 무례함</li>\n</ul>\n</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class SelectableTextList(\n    val contents: List&lt;String&gt;,\n    var selectedIndex: Int? = null\n)\n\nclass CopyRowAction(val list: SelectableTextList) {\n    fun isActionEnabled(): Boolean = list.selectedIndex != null\n    fun executeCopyRow() {\n        val index = list.selectedIndex!!\n        val value = list.contents[index]\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li><code>!!</code>를 사용하여 발생하는 에러 스택 트레이스에는 몇번째 줄인지에 대한 정보가 들어있지 않다.\n<ul>\n<li>여러 <code>!!</code> 단언문을 한 줄에 함께 쓰는 일을 피하는 것이 좋다.</li>\n</ul>\n</li>\n</ul>\n<h2 id=\"-78-let-함수\" style=\"position:relative;\"><a href=\"#-78-let-%ED%95%A8%EC%88%98\" aria-label=\" 78 let 함수 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 7.8 let 함수</h2>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun sendEmailTo(email: String) {\n    println(&quot;Sending email to $email&quot;)\n}\n\nfun main() {\n    var email: String? = &quot;yole@gmail.com&quot;\n    email.let { sendEmailTo(it) }\n    email = null\n    email?.let { sendEmailTo(it) }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>let을 사용하는 가장 흔한 용례는 널이 될 수 있는 값을 널이 아닌 값만 인자로 받는 함수에 넘기는 경우이다.</li>\n<li>let 함수는 자신의 수신 객체를 인자로 전달받은 람다에 넘긴다.</li>\n<li>아주 긴 식이 있고 그 값이 null이 아닐 때 수행해야 하는 로직이 있을 때 let을 쓰면 훨씬 더 편하다.</li>\n</ul>\n<h2 id=\"-79-직접-초기화하지-않는-널이-아닌-타입-지연-초기화-프로퍼티\" style=\"position:relative;\"><a href=\"#-79-%EC%A7%81%EC%A0%91-%EC%B4%88%EA%B8%B0%ED%99%94%ED%95%98%EC%A7%80-%EC%95%8A%EB%8A%94-%EB%84%90%EC%9D%B4-%EC%95%84%EB%8B%8C-%ED%83%80%EC%9E%85-%EC%A7%80%EC%97%B0-%EC%B4%88%EA%B8%B0%ED%99%94-%ED%94%84%EB%A1%9C%ED%8D%BC%ED%8B%B0\" aria-label=\" 79 직접 초기화하지 않는 널이 아닌 타입 지연 초기화 프로퍼티 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 7.9 직접 초기화하지 않는 널이 아닌 타입: 지연 초기화 프로퍼티</h2>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class MyService {\n    fun performAction(): String = &quot;Action Done!&quot;\n}\n\nclass MyTest {\n    private var myService: MyService? = null\n    \n    @BeforeAll fun setUp() {\n        myService = MyService()\n    }\n    \n    @Test fun testAction() {\n        assertEquals(&quot;Action Done!&quot;, myService!!.performAction())\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>이 코드는 보기 나쁘다.</li>\n<li>코틀린에서는 클래스 안의 널이 아닌 프로퍼티를 생성자 안에서 초기화하지 않고 특별한 메서드 안에서 초기화할 수는 없다. 일반적으로 생성자에서 모든 프로퍼티를 초기화해야 한다.</li>\n<li>프로퍼티 타입이 널이 될 수 없는 타입이라면 반드시 널이 아닌 값으로 초기화해야 한다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class MyTest {\n    private lateinit var myService: MyService\n\n    @BeforeAll fun setUp() {\n        myService = MyService()\n    }\n\n    @Test fun testAction() {\n        assertEquals(&quot;Action Done!&quot;, myService.performAction())\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li><code>lateinit</code> 변경자를 붙이면 프로퍼티를 나중에 초기화할 수 있다.</li>\n<li>지연 초기화 프로퍼티는 항상 var여야한다.</li>\n</ul>\n<h2 id=\"-710-안전한-호출-연산자-없이-타입-확장-널이-될-수-있는-타입에-대한-확장\" style=\"position:relative;\"><a href=\"#-710-%EC%95%88%EC%A0%84%ED%95%9C-%ED%98%B8%EC%B6%9C-%EC%97%B0%EC%82%B0%EC%9E%90-%EC%97%86%EC%9D%B4-%ED%83%80%EC%9E%85-%ED%99%95%EC%9E%A5-%EB%84%90%EC%9D%B4-%EB%90%A0-%EC%88%98-%EC%9E%88%EB%8A%94-%ED%83%80%EC%9E%85%EC%97%90-%EB%8C%80%ED%95%9C-%ED%99%95%EC%9E%A5\" aria-label=\" 710 안전한 호출 연산자 없이 타입 확장 널이 될 수 있는 타입에 대한 확장 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 7.10 안전한 호출 연산자 없이 타입 확장: 널이 될 수 있는 타입에 대한 확장</h2>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun verifyUserInput(input: String?) {\n    if (input.isNullOrBlank()) {\n        println(&quot;Please fill in the required fields&quot;)\n    }\n}\n\nfun main() {\n    verifyUserInput(&quot; &quot;)\n    verifyUserInput(null) // 예외 발생하지 않음.\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>메서드 호출이 null을 수신 객체로 받고 내부에서 null을 처리하게 할 수 있다.\n<ul>\n<li>확장 함수에서만 가능</li>\n<li>일반 멤버 호출은 객체 인스턴스를 통해 디스패치되므로 그 인스턴스가 null인지 여부를 검사하지 않는다.</li>\n</ul>\n</li>\n<li>널이 될 수 있는 타입의 확장 함수는 자신의 수신 객체가 null일 때 어떻게 해야 하는지 스스로 안다.\n<ul>\n<li>안전한 호출 없이도 호출 가능</li>\n</ul>\n</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun sendEmailTo(email: String) {\n    println(&quot;Sending email to $email&quot;)\n}\n\nfun main() {\n    val recipient: String? = null\n    recipient.let { sendEmailTo(it) } // 안전한 호출을 사용하지 않아 널이 될 수 있는 타입으로 취금\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>let은 this가 null인지 검사하지 않는다.</li>\n<li>let을 사용할 때 수신 객체가 null이 아닌지 검사하고 싶다면 안전한 호출 연산인 <code>?.</code>를 사용해야 한다.</li>\n</ul>\n<h2 id=\"-711-타입-파라미터의-널-가능성\" style=\"position:relative;\"><a href=\"#-711-%ED%83%80%EC%9E%85-%ED%8C%8C%EB%9D%BC%EB%AF%B8%ED%84%B0%EC%9D%98-%EB%84%90-%EA%B0%80%EB%8A%A5%EC%84%B1\" aria-label=\" 711 타입 파라미터의 널 가능성 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 7.11 타입 파라미터의 널 가능성</h2>\n<ul>\n<li>타입 파라미터 T를 클래스나 함수 안에서 타입 이름으로 사용하면 이름 끝에 물음표가 없더라도 T가 널이 될 수 있는 타입이다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun &lt;T&gt; printHashCode(t: T) {\n    println(t?.hashCode()) // 안전한 호출 사용\n}\n\nfun main() {\n    printHashCode(null)\n    // null\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li><code>printHashCode</code> 호출에서 타입 파라미터 T에 대해 추론한 타입은 널이 될 수 있는 Any? 타입이다.</li>\n<li>타입 파라미터가 널이 아님을 확실히 하려면 널이 될 수 없는 타입 상계를 지정해야 한다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun &lt;T: Any&gt; printHashCode(t: T) {\n    println(t.hashCode()) // 안전한 호출 사용\n}\n\nfun main() {\n    printHashCode(null) // error\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>타입 파라미터는 널이 될 수 있는 타입을 표시하려면 반드시 물음표를 타입 이름 뒤에 붙여야 한다는 규칙의 유일한 예외이다.</li>\n</ul>\n<h2 id=\"-712-널-가능성과-자바\" style=\"position:relative;\"><a href=\"#-712-%EB%84%90-%EA%B0%80%EB%8A%A5%EC%84%B1%EA%B3%BC-%EC%9E%90%EB%B0%94\" aria-label=\" 712 널 가능성과 자바 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 7.12 널 가능성과 자바</h2>\n<h3 id=\"-7121-플랫폼-타입\" style=\"position:relative;\"><a href=\"#-7121-%ED%94%8C%EB%9E%AB%ED%8F%BC-%ED%83%80%EC%9E%85\" aria-label=\" 7121 플랫폼 타입 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 7.12.1 플랫폼 타입</h3>\n<ul>\n<li>플랫폼 타입은 코틀린이 널 관련 정보를 알 수 없는 타입\n<ul>\n<li>널이 될 수 있는 타입 or 널이 될 수 없는 타입으로 처리해도 된다.</li>\n<li>컴파일러는 모든 연산을 허용</li>\n</ul>\n</li>\n<li>자바 API를 다룰 때는 조심해야 한다.\n<ul>\n<li>대부분의 라이브러리는 널 관련 어노테이션을 쓰지 않는다.</li>\n</ul>\n</li>\n<li>코틀린에서 플랫폼 타입을 선언할 수는 없다.</li>\n<li>자바에서 가져온 널 값을 널이 될 수 없는 코틀린 변수에 대입하면 실행 시점에 대입이 이뤄질 때 예외가 발생</li>\n</ul>\n<h3 id=\"-7122-상속\" style=\"position:relative;\"><a href=\"#-7122-%EC%83%81%EC%86%8D\" aria-label=\" 7122 상속 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 7.12.2 상속</h3>\n<ul>\n<li>코틀린에서 자바 메서드를 오버라이드할 때 그 메서드의 파라미터와 반환 타입을 널이 될 수 있는 타입으로 선언할지 널이 될 수 없는 타입으로 선언할지 결정해야 한다.</li>\n<li>자바 클래스나 인터페이스를 코틀린에서 구현할 경우 널 가능성을 제대로 처리하는 것이 중요\n<ul>\n<li>코틀린 컴파일러는 널이 될 수 없는 타입으로 선언한 모든 파라미터에 대해 널이 아님을 검사하는 단언문을 만들어준다.</li>\n</ul>\n</li>\n</ul>","excerpt":"📖 7.1 NullPointerException을 피하고 값이 없는 경우 처리: 널 가능성 코틀린을 포함한 최신 언어에서 null에 대한 접근 방법은 가능한 이 문제를 실행 시점에서 컴파일 시점으로 옮기는 것 널이 될 수 있는지 여부를 타입 시스템에 추가하으로써 컴파일러가 여러 가지 오류를 컴파일 시 미리 감지해서 실행 시점에 발생할 수 있는 예외의 가능성을 줄일 수 있다. 📖 7.…","fields":{"slug":"/backend/kotlin-in-action/7장-널이_될_수_있는_값/"},"frontmatter":{"title":"Kotlin in Action - 7장 널이 될 수 있는 값","thumbnail":{"childImageSharp":{"fluid":{"src":"/static/f7f7ddfa31d1614405dc5af1487b9ec4/9c94d/kotlin-in-action.png"}}},"draft":false,"category":"Back-End","tags":["Kotlin"],"date":"April 13, 2025"}}}},"staticQueryHashes":["2374173507","2996537568","3691437124"]}