kotlin을 사용하면서 java와 다른 점들과 샘플 코드들을 정리 한다.
0. main 함수가 클래스 안에 있을 필요가 없다.
main 함수를 클래스 없이 정의 하면 파일명으로 클래스가 생성되고 그안에 main 함수가 들어가게 된다.
1. 기본 타입들이 모두 클래스 이다.
기본 타입들은 java와 크게 다르지 않으나 모두 클래스 형태로 되어 있다.
2. 컴파일 시점에 기본 타입의 범위에 대한 체크가 이루어진다.
val a: Byte = 500 처럼 최대 값을 벗어나는 값으로 초기화를 할때 에러를 발생 시킨다.
초기 잘못된 타입에 대한 overflow를 예방 할수 있다.
3. 함수 정의는 fun, 변수 정의는 val, var을 앞에 붙인다.
fun foo(a: Int): Int // fun 함수명(파라메터): 반환타입 형식으로 함수를 정의 한다.
변수앞에는 val, var을 붙이고 val 은 value로 변경 되지 않는 값, var은 variable로 변경 되는 값을 의미한다.
4. for 루프 사용하기
여러 스타일로 사용이 가능하다.
5. if, when
val c = if (a == 5) "a is 5" else "a is not 5" 처럼 if 문을 값으로 사용할수 있다. 이때 항상 else가 있어야 한다.
when은 switch 대신 사용한다고 생각하면 된다. default 대신 else를 사용한다.
when에서 사용하는 값은 기본 타입에서 클래스 객체까지 사용되고,
','를 사용하여 여러 값을 하나의 항목으로 묶을수 있다.
6. 멤버 변수 정의 하기
클래스 명 파라메터를 val, var로 정의를 하면 멤버 변수가 된다. data class 타입에서 주로 사용 된다.
멤버 변수를 전달 받은 파라메터로 초기화 가능 하고, init 블럭을 사용해서 초기화 할수도 있다.
var 변수의 경우 lateinit 을 사용하여 초기화 시점을 늦출수 있다.(사용하기 전에 초기화 하면 된다.)
lateinit은 val 변수에는 사용할수 없다. val은 값 변경이 되지 않아 생성시점에 초기화 되어야 한다.
7. getter, setter 정의 하기
Java 에서는 get~, set~ 메소드를 정의 해야 하나 kotlin에서는 멤버변수 밑에 get(), set(value)를 붙여 주면 된다.
간단하게 getter, setter가 정의 되고, 변수를 사용하듯이 값을 할당 하거나 사용하면 자동으로 set, get이 호출된다.
8. 상속 사용하기
kotlin의 class는 자바의 final class 이다. 상속이 되지 않는다.
kotlin의 open class는 자바의 class 이다. 상속이 가능하다.
overriding 가능한 함수는 앞에 "open"을 붙여준다. 사용할때는 "override" 를 앞에 붙인다.
추상 클래스는 "abstract" 키워드를 사용하여 정의 한다.
9. null 안정성 - 1
변수를 정의 할때 "?"를 붙여 null 사용여부를 결정한다.
var testName: String? = null
사용 할때 "!!"를 붙이면 java에서 사용할때처럼 null 값일 경우 null pointer exception이 발생한다.
"?"를 붙여서 사용한다면 null 값을 경우 아무런 동작을 하지 않는다.
dog.printName() // compile error cat2.printName()
둘다 if 문에서 null 체크를 했으나 하나는 컴파일 에러가 발생하고, 하나는 에러가 발생하지 않는다.
차이는 변수의 값이 if 문 이후 변경이 가능한지 여부이다.
dog은 멤버 변수로 멀티 스레드로 동작할 경우 if문을 지난 직후 다른 스레드에서 변경하는 상황이 발생할수 있다.
cat2는 로컬 변수로 함수내에서 변경이 불가능 하여 null 체크 후 "." 만으로 사용이 가능 하다.
10. null 안정성 - 2
dog?.let 은 dog이 null 이 아닐 경우에만 동작하는 블럭을 정의 하고 dog을 "it"을 사용하여 접근한다.
엘비스 연산자 "?:"는 if 문을 간소화 해준다.
11. data 클래스
class 명 앞에 data를 붙여 정의 하는 것으로 생성자 파라메터에 정의 값이 동일할 경우 == 연산시 true를 리턴한다.
동일한 객체인지를 확인 할때는 "==="를 사용한다.
data 클래스는 내부적으로 copy, equals 등 몇가지 메소드를 정의한다.(java 코드로 변환해서 비교 하기 추천)
12. 배열 사용하기
arrayOf 를 통해 값이 설정된 배열을 리턴한다.
배열의 값은 변경이 가능하다(List 와 비교 하면 어떤 의미인지 알수 있다.)
값 설정외 갯수를 정의 하는 방법도 있고 "IntArray(10) { index -> index }" 처럼 초기값을 설정하는 것이 가능하다.
Int 타입 처럼 숫자 관련 배열의 경우 sum, average 등의 자주 사용하는 연산 함수들이 추가 된다.
13. List, MutableList
주요 데이터 저장 타입에는 순서가 있는 List, 중복값 없는 Set, key 와 연결 되는 Map 이 있다.
이 타입들은 값 변경이 불가능하고 변경을 원할 경우 Mutable 이 붙어 있는 타입으로 정의 한다.(MutableList...)
14. Lambda 식
요즘 들어 개발 언어들을 보면 lambda 식을 지원한다는 내용이 자주 보인다.(c++, java 등)
그만큼 알고 사용하면 유용한 개발 방식이다.
주로 사용하는 방식은 생성된 객체의 변수를 다른 객체에서 접근하여 원하는 결과를 만들고 싶을때 사용한다.????
말하고 보니 설명이 쉽지 않은 부분이지만 여러 샘플 코드들을 보면서 이해 하길 추천한다.
예제 코드는 { num -> list.contains (num) } 가 내부 객체로 생성되고 그 참조가 LamdaTest 에 전달된다.
lambda 식이 내부 객체로 동작하는 부분을 이해하는게 중요하다.
15. coroutine 은 멀티 스레드가 아니다.
처음 봤을때는 가벼운 동시 작업 이라고 해서 멀티 스레드 개념으로 이해 했으나
context switching 과 관련이 없이 수행되는 동시 작업이라 동작이 완전히 다르다.
coroutine 용으로 사용되는 delay를 호출할 경우 그 제어권이 scope 관리로 넘어 간다.
delay 시간에 맞춰 각 coroutine 이 호출 될것으로 생각 하지만 멀티 스레드와 달리 호출이 될것에 대한 보장이 약하다.
coroutine 실행이 짧고 delay 가 호출되어 scope 관리로 넘어 갈 경우는 크게 문제가 되지 않지만
coroutine 실행이 길어질 경우 동일 scope내 coroutine들이 제시간에 실행 되는 것이 보장 되지 않는다.
sleep을 넣어 보면 sleep 끝날때까지 다른 coroutine 들이 동작 하지 않는다.
실행 시간이 짧은 비동기 실행이 필요할때 사용한다.