1️⃣ 오늘의 Keyword
- 인수 (argument)
- 기본인수 (default argument), 명명된 인수
- infix
- vararg
- tailrec
- Array 배열
- mutable, immutable
- iterator
2️⃣ 학습 내용 및 예시
- Argument(인수) : 함수를 호출하면서 매개변수로 전달하는 값.
- 기본인수 = 매개변수로 인수를 명시하지 않아도 기본값을 적용, 불필요한 오버로딩을 줄여줌.
fun sayHello(name: String = "kkang") { println("Hello!!" + name) }
- 명명된 인수 = 인수를 매개변수에 대입할 때, 매개변수명을 명시하는 방법
fun sayHello(name: String = "kkang", no: Int){ println ("Hello!!" + name) } fun main(args: Array<String>) { // sayHello(10) //error sayHello("lee", 20) sayHello(no=10) sayHello(name="kim", no=20) }
- infix
- 중위 표현식을 함수 호출에도 사용이 가능
- infix 라는 예약어로 선언
- 클래스의 멤버 함수로 선언되거나 혹은 클래스의 extension 함수인 경우 (가능조건1)
- 하나의 매개변수를 가지는 함수의 경우 (가능조건2)
//====>extension 기법.. infix fun Int.myIntFun(x: Int): Int { return x + x } class FunClass { //클래스의 멤버함수...그리고 하나의 매개변수... infix fun myFun(a: Int){ println("data : $a") } } fun main() { val obj = FunClass() obj.myFun(10)//ok... obj myFun 10 //중위 표현식 10.myIntFun(10) 10 myIntFun 10 //중위 표현식 }
- 가변인수
- vararg를 매개변수에 선언하여 지정
- 함수당 하나의 파라미터에만 허용
- vararg 파라미터는 마지막에 오는 것이 권장됨.
- 이미 배열인 값을 전달할 때는 스프레드 연산자(*) 필요
fun testFun(a1: Int, vararg a2: String){ //가변 인수는.. 함수 내부에서는 배열이다.. for(a in a2){ println(a) } } testFun(10, "hello","world") testFun(10, "hello","world", "kim")
- 재귀 함수
- 함수 내에서 자신의 함수를 다시 호출하는 것
- tailrec 꼬리 재귀 함수
- 코드 작성은 재귀함수로 → 컴파일러가 이를 반복문으로 최적화
- 스택 오버플로우를 방지함.
- Collection type
- 배열 Array
- 선언
- val a: Array = arrayOf(10, 20, 30) //Any type, size 고정
- val a: Array = arrayOf<Int>(10, 20, 30) //Int type만
- val a: Array = Array(3, {0}) // 각 매개변수는 size, 배열데이터(람다함수)
- arrayOf<Int>, Array<Int>(3, {3}) ⇒API면에서 활용이 편하다
- intArrayOf, IntArray(3, {0}) ⇒Java와의 호환문제로 기초타입과 관련된 함수가
따로 존재함. 사용해도 문제없다. - Collection 타입의 클래스들은 mutable, immutable 클래스로 구분
- immutable - size(), get() 함수만 제공
- mutable - size(), get() 외에 add(), set() 함수 제공
- MutableList<String>, ImmutableList<String> 타입은 타입유추가능
immutableListOf(), mutableListOf() 각각의 함수로 타입지정. - iterator
- hasNext() 함수와 next() 함수를 이용해 순차적 이용
배열(Array) | index 이용 | size 고정 | 중복 o |
List | index 이용 | size 가변 | 중복 o |
Set | index 이용 | size 가변 | 중복 x |
Map | key / value | size 가변 | Key: 중복불가 / Value: 중복허용 |
val list = listOf<String>("hello", "world") val iterator1 = list.iterator() while (iterator1.hasNext()) { //데이터가 더 있는지 판단.. println(iterator1.next()) //현 순서의 데이터 획득..
❓ 이해 안 된 부분 / 도움 요청
‼️오늘 느낀 점
- 상수변수, 메모리 할당에 관련된 개념을 스스로 공부해봐야겠다.
- java와의 호환성 때문에 IntArray, DoubleArray 같은 기초타입과 관련된 함수가 존재한다고하는데 java와 다르게 Kotlin 에서는 타입을 기본적으로 객체로 여기고, java에서처럼 Integer.xxx 같은 래핑, 언래핑을 컴파일 타임에서 신경쓰지 않아도 되도록한 것과 관련이 있는지 알아봐야겠다
⇒ - 코틀린이
IntArray,DoubleArray같은 특수 배열 타입을 제공하는 이유는 코틀린의 "모든 것은 객체다"라는 철학과 자바의 "원시 타입(Primitive Type) 성능" 사이의 간극을 메우기 위해서 - 코틀린의 철학: "모든 것은 객체"
- 코틀린에서는
Int,Double등을 선언할 때 일반 객체처럼 다룹니다. 자바처럼int(원시 타입)와Integer(래퍼 클래스)를 구분해서 쓰지 않아도 됩니다. - 코틀린:
val a: Int = 10(자동으로 상황에 맞춰 최적화) - 자바:
int a = 10;또는Integer a = 10;(개발자가 선택) - 코틀린 컴파일러는 똑똑해서, 가능한 한 성능이 좋은 원시 타입(int)으로 변환하려 노력하지만, 제네릭(Generic)을 사용할 때는 어쩔 수 없이 객체 타입(Integer)을 사용하게 됩니다.
Array<Int>vsIntArray의 결정적 차이Array<Int> (Generic Array)- 자바의
Integer[]로 컴파일됩니다. - 숫자 하나하나가 객체로 포장(Boxing)되어 메모리에 저장됩니다.
- 문제점: 숫자가 많아지면 메모리 사용량이 늘어나고 성능이 떨어집니다.
IntArray(Primitive Array)- 자바의
int[]로 컴파일됩니다. - 숫자가 객체로 감싸지지 않고 생으로(Primitive) 연속된 메모리에 저장됩니다.
- 장점: 자바와의 100% 호환성은 물론, 메모리 효율과 연산 속도가 압도적으로 빠릅니다.
- 컴파일 타임의 자동 최적화
- 일반 변수: 코틀린에서
val x: Int = 5라고 쓰면, 컴파일러는 내부적으로 자바의int x = 5로 변환합니다. (Boxing 오버헤드 없음) - 컬렉션:
List<Int>를 쓰면 자바 제네릭 규칙상 어쩔 수 없이Integer객체로 다뤄집니다. - 배열: 배열만큼은 성능이 매우 중요한 영역이라, 코틀린은
IntArray,LongArray등을 별도로 만들어 개발자가 "나는 자바의 원시 타입 배열(int[])을 쓸 거야"라고 명시할 수 있게 해준 것입니다. - 요약 및 결론
IntArray등이 존재하는 이유: 자바의 원시 타입 배열(int[])이 가진 성능 이점을 그대로 누리면서, 자바 라이브러리와 통신할 때 데이터 타입을 맞추기 위함입니다.- 컴파일러의 역할: 코틀린은 개발자가
Integer.valueOf()같은 복잡한 래핑 과정을 고민하지 않게 해주지만, 최적의 성능이 필요한 배열 작업에서는Array<Int> 대신IntArray를 선택하도록 선택지를 제공하는 것입니다.

