코틀린 진입점 : main()
main() 함수가 있는 파일 이름을 기준으로 자바 클래스가 자동 생성됩니다.
Tools>Kotlin>Show Kotlin Bytecode → Decompile 버튼으로 확인가능 합니다.
JVM 메모리 영역
코드 영역 : 명령어가 들어가는 영역
데이터 영역 : 정적 변수나 문자열 등이 들어가는 정적 메모리 영역
힙 영역 : 실행 중 생성되는 객체가 저장되는 동적 메모리 공간
스택 영역 : 코드 블록 내에서 호출되는 변수나 함수가 임시로 저장되는 메모리 영역
변수
변수의 선언 - val, var
val : 읽기 전용 변수 - 최초로 지정한 변수의 값으로 초기화하고 더 이상 바꿀 수 없습니다.
var : 값을 변경할 수 있음
* val로 변수를 선언해두고, 변경이 필요할 때 var로 바꾸는 방법을 권장합니다.
var username : String = "Kildong"
var : 선언 키워드
username : 변수 이름
String : 자료형
"Kildong" : 값
코틀린은 자료형을 추론할 수 있기 때문에, 다음과 같이 사용할 수도 있습니다.
* 이 경우에는 초기값을 반드시 지정해주어야 합니다.
var username = "Kildong"
자료형 - 참조형 자료형만 사용
코틀린에서는 참조형 자료형만 사용합니다.
참조형의 경우 실제 객체는 힙에 저장됩니다.
스택에는 참조 주소가 있습니다.
컴파일을 거치면서 참조형이 기본형으로 바뀝니다. 성능 이슈가 없다는 것입니다.
정수 자료형
Int, Long, Short, Byte
실수 자료형 : Float, Double
논리 자료형 : Boolean
문자 자료형 : Char
문자열 자료형 : String
val exp01 = 123 // Int형
val exp02 = 123L // L : Long
val exp03 = 0x0F // 0x : 16진수
val exp04= 0b00001011 //0b : 이진수
*아스키코드 : 1바이트 - 256개의 문자
* 유니코드 : 2바이트 - 65536개의 문자
코틀린은 힙 영역의 String Pool이라는 공간에 문자열 값을 저장해 두고, 이 값을 참조하게 합니다.
표현식과 $기호를 사용해 문자열 출력
var a=1
val str1 = "a= $a"
val str2 = "a = ${a+2}"
형식화된 다중 문자열 출력 - """
- 작성한 내용과 완전 동일하게 출력
* 2의보수, 부동소수점 제대로 이해하기는 다음에 공부
자료형에 별명 붙이기 - typealias
- 변수의 자료형이 복잡한 구조를 가지면 자료형에 별명을 붙일 수 있습니다.
typealias Username = String
val user : Username = "Kildong"
Null 허용 - ?
- 물음표 기호를 활용해 Nullable 변수를 지정할 수 있습니다.
세이프 콜(?)과 non-null 단정(!!) 기호 활용하여 null을 허용한 변수 사용
- 세이프콜 : null이 할당되어 있을 가능성이 있는 변수를 검사하여 안전하게 호출되도록 도와주는 기법
null인지 확인하고, null이면 함수에 접근하지 않고 null리턴
- non-null 단정기호(!!) : 변수에 할당된 값이 null이 아님을 단정짓습니다.
null이 할당되어 있어도 컴파일은 잘 됩니다. 하지만, 실행 중 NPE발생시킵니다.
세이프콜과 엘비스 연산자(?:)를 활용해 null 허용한 변수 더 안전하게 사용하기
- 엘비스 연산자 : 변수가 null인지 아닌지 검사, null이 아니면 왼쪽 식을 그대로 실행, null이면 오른쪽 식 실행
var str1 : String? = "hello Kotlin"
// str1=null
println("str1 : $str1 length : ${str1?.length}") // 세이프콜
println("str1 : $str1 length : ${str1!!.length}") // non-null 단정 기호
println("str1 : $str1 length : ${str1?.length ?: -1}") // 엘비스 연산자
자료형 변환과 비교
- 같은 자료형만 비교가 가능합니다.
자료형 변환 - toXXXX
java 처럼 int를 double에 할당하는 것이 불가능합니다.
. toSomething 메서드를 통해서 자료형을 변환합니다.
- toInt, toDouble, toChar, toFloat, toShort, toByte, toLong
var d : Double = 10.3
var a : Int = d.toInt()
기본형과 참조형 비교 - 값(==), 참조주소(===)
값만 비교 : ==
참조 주소 비교 : ===
자료형 검사 - is, !is
- Any형은 자료형 검사할때 검사하는 자료형으로 스마트 캐스트됩니다.
스마트 캐스트 - 자동으로 자료형 변환
as에 의한 스마트 캐스트
val x : String = y as String
val x : String? = y as? String // null 가능성까지 고려하면
묵시적 변환
- Any형 : 자료형이 특별히 정해지지 않은 경우에 사용합니다.
- 모든 클래스의 뿌리입니다.
코틀린 연산자
산술 연산자 : +, -, *, /, %
대입 연산자 : =, +=, -=, *=, /=, %= 변수에 값 할당하는 연산자
증가, 감소 연산자 : ++, --
비교연산자 : >, <, >=, <=, ==, ===, !=, !==
논리연산자 : &&, ||, !
비트 연산자 : ex) 4.shl(), shr(), ushr(), and(), or(), xor(), inv()
shl : 비트를 왼쪽으로 민다. 부호 있음
shr : 비트를 오른쪽으로 밉니다. 부호 있음
ushr : 제일 왼쪽에 0을 밀어 넣으면서 오른쪽으로 이동, 부호 없음
and : 둘다 1이면 1, 아니면0
or : 둘 중 하나라도 1이면 1, 아니면 0
xor : 둘이 같으면 1 , 다르면 0
inv : 1은 0으로, 0은 1로
xor활용 두 값 swap하기
함수
fun sum(a: Int, b: Int) : Int{
var sum = a+b
return sum
}
fun sum(a : Int, b: Int): Int = a+b
fun sum(a : Int, b: Int) = a+b
인자 : 함수를 호출할 때, 파라미터
매개변수 : 함수 선언할 때의 파라미터 부분
스택프레임 : 함수가 호출될 때마다 해당 정보는 스택 메모리에 쌓입니다. 이를 스텍프레임이라 합니다.
스택은 메모리의 높은 주소에서 낮은 주소 방향으로 생성됩니다.
힙 영역에는 동적으로 생성된 객체 정보가 담겨져 있습니다. 낮은 주소에서 높은 주소로 정보 저장를 저장합니다.
반환값이 없는 함수 - Unit
생략하거나, Unit으로 반환타입 설정합니다.
java의 void와는 다릅니다.
fun printsum(a: Int, b: Int) : Unit{
println(a+b)
}
fun printsum(a: Int, b: Int){
println(a+b)
}
매개변수 활용
default값 설정~!
fun add(name : String, email : String = "default"){
}
매개변수 이름과 함께 함수를 호출할 수도 있습니다.
add(email ="wj@naver.com", name = "wj")
가변인자 : vararg
- 여러 개의 인자를 전달받는 함수
fun normalVarargs(vararg counts : Int){
for( num in counts){
print("$num")
}
}
함수형 프로그래밍
순수 함수
- 같은 인자에 대해 항상 같은 값을 반환한다.
- 함수 외부의 어떤 상태도 바꾸지 않는다.
람다식
람다 대수 : 이름 없는 함수로 2개 이상의 입력을 1개의 출력으로 단수화한다.
일급 객체
함수형 프로그래밍에서 '함수 = 일급 객체'
- 일급 객체는 함수의 인자로 전달할 수 있다.
- 일급 객체는 함수의 반환값에 사용할 수 잇다.
- 일급 객체는 변수에 담을 수 있다.
함수가 일급 객체면 일급 함수라고 부릅니다.
이 일급 함수에 이름이 없으면 람다식이라고 부릅니다.
고차 함수
다른 함수를 인자로 사용하거나 함수를 결과값으로 반환하는 함수
함수형 프로그래밍의 정의와 특징
- 순수 함수를 사용해야한다.
- 람다식을 사용할 수 있다.
- 고차 함수를 사용할 수 있다.
람다식을 인자나 반환값으로
val multi : (Int, Int) -> Int = {x : Int, y : Int -> x*y} // 전체표현
val multi = {x : Int, y: Int -> x*y} // 선언 자료형 생략
val multi : (Int, Int) -> Int = {x, y -> x * y} //람다식 매개변수 자료형의 생략
람다식은 많은 코드를 간략화하고 함수 자체를 인자나 매개변수로 이용할 수 있어 프로그램의 효율성도 높일 수 있습니다.
fun sum(x : Int, y : Int) = x + y
fun funcParam(a : Int, b : Int, c: (Int, Int)->Int):{
return c(a,b)
}
->
funcParam(3, 2, ::sum) // 람다함수가 아닌경우 이렇게 불러와서 쓸 수 있다.
// 일반 변수에 값처럼 할당할 수도 있다.
val func = ::sum
hello(::text) // 함수 참조 기호
hello({a, b-> text(a,b)}) // 람다식 표현
hello{a, b-> text(a,b)} // 소괄호
매개변수로 람다식 하나만 있는 경우, 사용할 때 소괄호를 생략할 수 있습니다.
람다식의 매개변수 개수에 따른 활용
매개변수 0개, 1개
fun main(){
//매개변수 없는 람다식
noParam({"Hello World"})
noParam{"Hello World"} // 매개변수가 없으면 화살표가 사용될 필요가 없다.
oneParam({a-> "Hello World! $a"})
oneParam{a-> "Hello World! $a"}
oneParam({"Hello World! $it"}) // 1개짜리 매개변수는 it으로 대체할 수 있습니다.
}
fun noParam(out : () -> String) = println(out())
fun oneParam(out : (String) -> String)}
println(out("OneParam"))
}
매개변수 2개 이상
fun main(){
morePara {a,b-> "Hello World! $a $b"} // 매개변수 이름 생략 불가
morePara {_,b-> "Hello World! $b"} // 안쓰고 싶은건 _로 처리합니다.
}
fun moreParam(out : (String, String) -> String){
println(out("OneParam", "TwoParam"))
}
만일, 일반 함수의 마지막 매개변수가 람다식이라면 함수의 소괄호 바깥으로 마지막 람다식을 뺄 수 있습니다.
fun main(){
withArgs("Arg1","Arg2", {a, b-> "Hello World! $a $b"})
// 마지막 인수가 람다식이라서 밖으로 뺄 수 있음
withArgs("Arg1","Arg2"){a, b-> "Hello World! $a $b"}
}
fun withArgs(a : String, b: String, out:(String, String)->String){
println(out(a,b))
}
2개 이상의 매개변수가 람다식이라면, 소괄호 생략 불가합니다.
fun main(){
// 마지막 인수가 람다식이라서 밖으로 뺄 수 있음
twoLambda({"FIRST"}, {a, b-> "Hello World! $a $b"})
twoLambda({"FIRST"}){a, b-> "Hello World! $a $b"}
}
fun twoLambda(first: (String)-> String, out:(String, String)->String){
println(out(a,b))
println(first("one"))
}
댓글