본문 바로가기
Language/코틀린

[Kotlin] Fast campus 강의 Android App 개발 (코틀린). 문법

by javapp 자바앱 2021. 10. 16.
728x90

[코틀린] Fast campus 패스트캠퍼스 내돈내산 안드로이드 앱 개발 코틀린편. 

문법

 

 


인텔리제이에서 코틀린 메인 함수 단축키: psvm 

fun main(args : Array<String>){...}

 

 

Number 숫자형

    // 숫자형 DataType 크기 순으로 선언
    var doublev : Double = 110.111  //8
    var floatv  : Float  = 110.1f   //4
    var longv   : Long   = 110L     //8
    var intv    : Int    = 20       //4
    var shortv  : Short  = 30       //2
    var bytev   : Byte   = 10       //1

    println(doublev)
    println(floatv)
    println(intv)

    // 크기변환 후 대입, 메소드 사용
    doublev = intv.toDouble()
    intv = doublev.toInt()

    println("byteStr: "+bytev.toString())

    val num ="123".toInt() + 10
    println(num)

결과

110.111
110.1
20
byteStr: 10
133

 

 


 

 

String 문자형

    var sLines = """
        asdf
    dff
123
    """
    println(sLines)

    var sName= "김이름"
    // 문자열 내에 변수 str 치환
    var sFormatter = "$sName : sName의 값"
    println(sFormatter)

    // 파이썬에서 print(f' ... {}') 랑 비슷
    var date ="1시"
    var sTime = "${ "지금 시각은 "+date }"
    println(sTime)

 

        asdf
    dff
123
    
김이름 : sName의 값
지금 시각은 1시

 


 

Any 형

// Any형은 동적 타입을 지원한다.
// null 은 ?로 정의
var everybody : Any

everybody = 1111
everybody = "문자열 테스트"
everybody = 222.1011
everybody = 12.00f

if (everybody !is String)
{
  if(everybody is Float){
  	println("float 입니다.")
  }
}

<결과>

float 입니다.

 

//    everybody.equals(other = Any?)
    println(everybody.equals(12.00f))

true

 

    //문자열 처리시 많이씀
    Allprint(1234)
    Allprint("Hello")

fun Allprint(a : Any) = println(a.toString())

Hello

 

 

    // Unit 형은 값이 없음을 정의하는 형
    // 넘겨진 파라미터가 1개이면 it 이다.
    var pFunc : (String) -> Unit={println(it)}
    pFunc("unit unit")

    // Nothin형은 미래가 없음을 알리는 형
//    TODO("실행하고 종료해버림..")


unit unit

 


 

함수

fun funByReturn(s : String) : Any?{
    return s
}

fun funByReturn(i:Int , s:String){
    println(i.toString()+s)
}

fun funByInline(i : Int, i2 : Int) = i * i2

fun funByNoParam(){
    println("funByNoParam")
}

// 고차함수 : 입력 함수로 받고 출력도 함수로
// Unit : void
fun higherFunc(f : () -> Unit){
    f()
}

// 함수를 정의한 변수
val funVar = { s : String -> println(s)}

// :: 함수 주소 값을 넘긴다. (* 포인터 개념)
val funcVarType : (String) -> Any? = ::funByReturn

 

// 메인
fun main()
{
    // fun 함수명(변수명 : 데이터크기,...):리턴값(return;}
    // 한 줄로 표현가능한 함수는 {} 대신에 = 으로 정의 가능
    fun three (n :Int) = 3 * n
    println(three(3).toString())

    // 함수형 변수의 값 : (변수 정의 -> 코드 구현)
    // 함수형 변수의 형 : (입력 정의 -> 리턴 정의)

    funByNoParam()
    funByReturn(31, " 숫자 입니다.")
    println(funByReturn("funByReturn 1 param"))
    println(funByInline(31, 10))

    funVar("Function Variable 1")
    println(funcVarType("Function Variable 2"))

    higherFunc( {println("Higer Function")} )
    higherFunc { ::funcVarType }
}

 

 


 

제어문

 

if 문은 java 와 유사, in, is 등과 함께 사용되어 유연하게 사용
반복문 for : for(변수 in 배열 or 범위)
반복문 while : while(조건)
case 문은 Any 타입과 사용,when(변수){조건 -> 실행..)
코틀린은 삼항 연산자가 없다.

 

 

 

조건문 if .. else

fun ifTest(a:Any?)
{
	// java 와 유사한 부분 제외
    if (a in (0..9)){
        println("0~9까지의 숫자: $a")
    }else if (a== null){
        println("null !")
    }else println("else")
}

0~9까지의 숫자: 9

 

 

반복문

fun loopTest(count : Int)
{
    for(i in (0..count)){
        println("i : "+ i)
    }

    //(0..count).forEach{println("foreach: $it : "+ it)}

    var i : Int = 0
    while ( i < count) {
        i++
        println("$i 입니다.(while)")
    }

}

i : 0
i : 1
i : 2
i : 3
i : 4
i : 5
i : 6
i : 7
i : 8
1 입니다.(while)
2 입니다.(while)
3 입니다.(while)
4 입니다.(while)
5 입니다.(while)
6 입니다.(while)
7 입니다.(while)
8 입니다.(while)

 

 

 

case문 : when

fun caseTest(o:Any?)
{
    when(o)
    {
        "Test" -> { println("문자: "+o)}
        is Int -> { println("숫자: "+o)}
        in (0..9) ->{ println("0부터 9까지 숫자 : "+ o)}
        else -> { println("error")}
    }
}

숫자: 3

 

 

    var str = " ABCDE"
    val result=when(str)
    {
        is String -> {true}
        else -> {false}
    }
    println(result)

true

 

 


 

 

레이블

 

Kotlin 에서 레이블은 매우 중요 : 함수형 언어이기에 리턴되는 곳을 명확히 해야할 필요가 있기 때문이다.

return 반환값
return @레이블 반환값 : 익명함수, 람다함수 구조

break@레이블, continue@레이블 :
break는 반복문 종료후 지정한 레이블로 나간다.
continue 는 다음 라인(뒷 라인) 무시하고 지정한 레이블 이동한다.

 

 

// 이런 방식으로 많이 쓰이진 않고
// 어떻게 돌아가는지 이해하는 정도
fun exitLoop()
{
    HereToExit@ for(i in 0..2)
    {
        for(j in 0.. 10)
        {
            if(j == 5) break@HereToExit
            println("i -> $i , j -> $j")
        }
        println("j loop end")
    }
    println("i loop end")
}

i -> 0 , j -> 0
i -> 0 , j -> 1
i -> 0 , j -> 2
i -> 0 , j -> 3
i -> 0 , j -> 4
i loop end

 

break 이라면 내부 for(j ㅑㅜ 0..10) 을 종료하지만
break@레이블 이면 외부 for 을 종료하여
i loop end 가 출력된다.

 

 

람다식, 범위 연산자

var lambdaReturn = Exit@{
    if(true) {
        return@Exit 3
    }
    1000
    // return 1000
}

 

fun main()
{
    (0..10).forEach {
        if(it > 3) return@forEach else println(it)
    }
}

3

 

Exit 으로 돌아가 종료한다.

 

람다 함수나 익명 함수 형식에서 반환 값을 가지고 싶을 때

유용하게 사용하는 것으로 보인다. 

//var funVar = { s : String -> return "ss"}

 

 


 

 

Collection 컬렉션

제네릭 타입 인터페이스

 

Kotlin에서 Collections는 열거형 데이터 관리하는 데 필수 클래스 집합
read-only : List -> listOf. 항목 데이터 타입 혼합 가능
rw : List -> mutableListOf. 제네릭(<>)으로 반드시 선언
Map : hashMapOf(to ..)

 

 

 

 

Immutable Collection

listOf : read-only

// val lst = listOf <Int> (1,"A",12.00f,false)
    val lst = listOf(1,"A",12.00f,true)
    println(lst.size)

4

listOf  , 제네릭을 쓰지 않으면 모든 타입의 값이 들어갈 수 있다.

 

* 상수 배열로 쓰인다.

val DAY_LIST = listOf("월", "화", "수")

 

 

 

 

 

리스트(List)

 

 

  저장되는 데이터에 인덱스를 부여한 컬렉션이며 중복된 값 입력 가능

  동적으로 리스트를 사용하기 위해서는 리스트 자료형 앞에 뮤터블(Mutable)이라는 접두어가 붙는다.

  mutableList, mutableMap, mutableSet

 

 

rw : List -> mutableListOf

제네릭(<>)으로 반드시 선언

    val lstEdiable = mutableListOf<String>() //class java.util.ArrayList
    lstEdiable.add("A")
    lstEdiable.add("B")

    for(s in lstEdiable)
    {
        println(s)
    }

A

B

 

 

 

Set

 

 

셋 (set)

  LinkedHashSet, HashSet

  중복을 허용하지 않는다.

  인덱스로 조회할 수 없고,  get 함수도 지원하지 않는다.

 

 

var set = mutableSetOf<String>()
set.add("JAN")
set.add("FEB")
set.add("MAR")
set.add("JAN")

기본 타입 : class java.util.LinkedHashSet

 

이것이 안드로이드다.

 

To HashSet

val hashset : Set<String> = set.toHashSet()
// class java.util.HashSet

 

 

 

 

 

Map

 

 

맵(Map) : Map<K, V>

  LinkedHasMap, HashMap

  키(Key) 와 값(Value)의 쌍으로 입력되는 컬렉션

  Keys are unique

 

var map = mutableMapOf<String, String>()
map.put("key1","value1")
map.put("key2","value2")

map.get("key1")
map.put("key1","수정 value")
println(map.get("key1"))

map.remove("key1")

 

    // 기본 타입 : LinkedHashMap
    val numbersMap = mutableMapOf("one" to 1, "two" to 2)


    // HasMap
    var map = hashMapOf(
            "A" to 1,
            "B" to 2
        )
    println(map["A"])

1

 

 

 


 

 

 

예외 처리와 Null 처리 (엘비스(?) , !! , ?. , ?:  , as?

    var divNumber = 0
    try{

    }catch (e : Exception){
        println(e)
    }finally {
        println("finally")
    }


    // 로직으로 막아주면 에러가 안뜬다.
    var addNumber : Int? = null

    //에러
    // var sum = addNumber + 100

    // 처리 방법 1
    if(addNumber != null){
        var sum = addNumber + 100
    }

    // 처리 방법 2 -> !! (종료) : 널(Null) 값이 안들어 온다는 보증 , 대신 Null 이면 종료
    var sum1 = addNumber !! + 100

    // 처리 방법 3 -> ?. (실행안됨)
    var sum2 = addNumber?.let{
        it + 100
    }
    var name: String? = null // 널값에 대해 안전하게 변수 지정 가능
    
    // 처리 방법 4 -> ?:
    var nullStr : String? = null

    // addStr라는 변수는 현재 null 이기때문에 결과적으로 name에 "이름" 라는 값이 들어가겠네요.
    val name: String = nullStr ?: "이름"
    println(name)

    // 함수 자체를 return 시키도록 만들 수 도 있습니다.
    val nameTwo: String = nullStr ?: return

    // addStr 라는 변수는 현재 null 이기때문에 결과적으로 NullPointerException 예외가 발생하겠네요.
    val nameThree: String = nullStr ?: throw NullPointerException()
    
    
    // 처리 방법 5 -> as?   ,   자료형 변환에 대해 안전하게 변환 할 수 있도록 함
    val value: Int = addNumber as? Int ?: 0 //Int 로 변환 할 수 없으므로 0으로 빠지게 됩니다.

 

 


 

 

 

댓글