ABOUT ME

Today
Yesterday
Total
  • TECHIT 앱 스쿨 2기: Android 21일차 (23.05.24)
    [THEC!T] 앱 스쿨2기 : Android 2023. 5. 25. 01:14
    728x90

    자료 출처 : 안드로이드 앱스쿨 2기 윤재성 강사님 수업 내용

     

    오늘의 시작은 예외처리부터 시작하였습니다.

     

    코틀린에서는 예외처리를 강제하지 않습니다.

    그렇기 때문에 만약 장애가 발생하게 된다면 프로그램이 중지되기 때문에 장애가 발생할 가능성이 있다면 개발자가 판단하여 작성하면 됩니다.

    문법은 자바와 동일합니다.

    fun main(){
        // try ~ catch
        try{
            val stringNum = "문자열을 숫자로 변환해보자"
            stringNum.toInt()
        } catch (e: Exception){
            println("장애 발생 시 실행됨.")
            println("e.printStackTrace() : ${e.printStackTrace()}")
        } finally {
            println("장애가 발생하든 안하든 반드시 실행해야 되는 기능이 있을 경우")
        }
    
        println("try ~ catch 문 이후에 작성한 코드는 문제 없이 실행된다.")
    }

    출력 결과

    장애 발생 시 실행됨.
    e.printStackTrace() : kotlin.Unit
    장애가 발생하든 안하든 반드시 실행해야 되는 기능이 있을 경우
    try ~ catch 문 이후에 작성한 코드는 문제 없이 실행된다.
    java.lang.NumberFormatException: For input string: "문자열을 숫자로 변환해보자"
    	at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
    	at java.base/java.lang.Integer.parseInt(Integer.java:652)
    	at java.base/java.lang.Integer.parseInt(Integer.java:770)
    	at StudyKt.main(study.kt:5)
    	at StudyKt.main(study.kt)

     

    다음으로는 스레드에 대해서 배웠습니다.

    쓰레드 또한 자바와 동일하게 상속을 받거나 인터페이스를 구현하여 사용하는 방법도 있지만, 고차함수를 이용하여 쓰레드를 이용할 수 있습니다.

    import java.lang.Math.random
    import kotlin.concurrent.thread
    
    fun main(){
        // 자바와 동일하게 상속을 받거나 인터페이스를 구현하여 사용하는 경우
        val t1 = Test1().start()
        val t2 = Thread(Test2())
        t2.start()
    
        // thread 고차 함수 사용
        // run 메서드에 들어갈 코드(쓰래드로 처리될 코드)
        // 익명함수나 람다식으로 작성해서 넣어주면 해당 코드는 쓰래드로 운영해준다.
        // start() 도 자동으로 호출하기 때문에 개발자가 명시적으로 호출하지 않아도 된다.
        thread {
            for(i in 1 .. 10){
                println("thread 고차 함수 :$i ")
            }
        }
    
    }
    
    class Test1 : Thread(){
        override fun run() {
            super.run()
            for(i in 1 .. 10){
                print("Test1 : $i ")
            }
        }
    }
    
    class Test2 : Runnable{
        override fun run() {
            for( i in 1 .. 10){
                println("Test2 : $i")
            }
        }
    }

    출력 결과

    Test2 : 1
    Test1 : 1 thread 고차 함수 : 1 
    Test1 : 2 Test2 : 2
    Test1 : 3 thread 고차 함수 : 2 
    Test1 : 4 Test2 : 3
    Test1 : 5 thread 고차 함수 : 3 
    Test1 : 6 Test2 : 4
    Test1 : 7 thread 고차 함수 : 4 
    Test1 : 8 Test2 : 5
    Test1 : 9 thread 고차 함수 : 5 
    Test1 : 10 Test2 : 6
    thread 고차 함수 : 6 
    Test2 : 7
    thread 고차 함수 : 7 
    Test2 : 8
    thread 고차 함수 : 8 
    Test2 : 9
    thread 고차 함수 : 9 
    Test2 : 10
    thread 고차 함수 : 10

     

     

    다음으로는 스트림에 대해서 학습하였습니다.

    스트림도 사용 방법 자체는 자바와 문법적 차이를 제외하면 크게 다른 점은 없습니다.

    자료형

    import java.io.*
    
    enum class Name(name: String){
        FILE_NAME("test1.dat")
    }
    
    fun main(){
        fileSave()
        fileLoad()
    }
    
    // 파일에 작성하는 함수
    fun fileSave(){
        val fos = FileOutputStream(Name.FILE_NAME.name)
        val dos = DataOutputStream(fos)
    
        dos.writeInt(10)
        dos.writeDouble(33.33)
        dos.writeUTF("문자열5")
    
        dos.flush()
        dos.close()
        fos.close()
        println("쓰기 완료")
    }
    
    // 파일에서 읽어오는 함수
    fun fileLoad(){
        val fis = FileInputStream(Name.FILE_NAME.name)
        val dis = DataInputStream(fis)
    
        val r1 = dis.readInt()
        val r2 = dis.readDouble()
        val r3 = dis.readUTF()
    
        println(r1)
        println(r2)
        println(r3)
    
        dis.close()
        fis.close()
        println("읽기 완료")
    }

    출력 결과

    쓰기 완료
    10
    33.33
    문자열5
    읽기 완료

     

    오브젝트 읽고 쓰기

    import java.io.*
    
    enum class Name(name: String){
        FILE_NAME("test2.dat")
    }
    
    fun main(){
        val oc = TC(100,200)
        fileSave(oc)
        val ic = fileLoad()
        ic.printSum()
    }
    
    // 파일에 작성하는 함수
    fun fileSave(save:TC){
        val fos = FileOutputStream(Name.FILE_NAME.name)
        val dos = ObjectOutputStream(fos)
    
        dos.writeObject(save)
    
        dos.flush()
        dos.close()
        fos.close()
        println("쓰기 완료")
    }
    
    // 파일에서 읽어오는 함수
    fun fileLoad(): TC{
        var fis = FileInputStream(Name.FILE_NAME.name)
        var dis = ObjectInputStream(fis)
    
        val load = dis.readObject() as TC
    
        dis.close()
        fis.close()
    
        println("읽기 완료")
        return load
    }
    
    
    // 객체 직렬화를 한 클래스
    class TC(var a1:Int, var a2: Int ) : Serializable {
        fun printSum(){
            println("a1: ${a1}, a2: ${a2}, a1 + a2 = ${a1 + a2}")
        }
    }

    출력 결과

    쓰기 완료
    읽기 완료
    a1: 100, a2: 200, a1 + a2 = 300

     

    스트림 이어쓰기 및 이어 읽기 는 코틀린으로 작성하는 것은 알려주시지 않았지만 검색하여 작성해 보았습니다.

    올바른 방법이 아닐 수 도 있습니다.

    참고로 종료기능은 따로 작성하지 않았습니다.

    import java.io.*
    import java.util.Scanner
    
    enum class Name(val fileName: String){
        FILE_NAME_STUDY("test4.txt")
    }
    
    fun main(){
        val scan = Scanner(System.`in`)
        println("추가되는 자료는 TC(count,200) 뿐 입니다.")
        // 잘 저장하고 읽어오는지 확인하기 위해
        var count = 1
        var selectNum = 0
        while(true){
            print("생성하여 저장하시겠습니까? 1.진행,2.중단 후 저장파일 확인 : ")
            selectNum = scan.nextInt()
            if(selectNum != 1) {
                fileLoad()
                continue
            }
            val oc = TC(count,200)
            count++
            fileSave(oc)
        }
    
    
    }
    
    
    // 파일에 작성하는 함수
    fun fileSave(save:TC){
    
        val fos = FileOutputStream(Name.FILE_NAME_STUDY.fileName,true)
        val dos = ObjectOutputStream(fos)
    
        dos.writeObject(save)
    
        dos.close()
        fos.close()
    
        println("쓰기 완료")
    }
    
    // 파일에서 읽어오는 함수
    fun fileLoad(){
        val result = ArrayList<TC>()
        val fis = FileInputStream((Name.FILE_NAME_STUDY.fileName))
        var dis: ObjectInputStream? = null
        while(true){
            try{
                dis = ObjectInputStream(fis)
                val readObj = dis.readObject() as TC
                result.add(readObj)
    
    
            } catch (e: Exception){
                if (dis != null) {
                    dis.close()
                }
                fis.close()
                break
            }
        }
        for(i in result) i.printSum()
    
    }
    
    
    // 객체 직렬화를 한 클래스
    class TC(var a1:Int, var a2: Int ) : Serializable {
        fun printSum(){
            println("a1: ${a1}, a2: ${a2}, a1 + a2 = ${a1 + a2}")
        }
    }

    출력 결과

    추가되는 자료는 TC(count,200) 뿐 입니다.
    생성하여 저장하시겠습니까? 1.진행,2.중단 후 저장파일 확인 : 1
    쓰기 완료
    생성하여 저장하시겠습니까? 1.진행,2.중단 후 저장파일 확인 : 2
    a1: 1, a2: 200, a1 + a2 = 201
    생성하여 저장하시겠습니까? 1.진행,2.중단 후 저장파일 확인 : 1
    쓰기 완료
    생성하여 저장하시겠습니까? 1.진행,2.중단 후 저장파일 확인 : 1
    쓰기 완료
    생성하여 저장하시겠습니까? 1.진행,2.중단 후 저장파일 확인 : 2
    a1: 1, a2: 200, a1 + a2 = 201
    a1: 2, a2: 200, a1 + a2 = 202
    a1: 3, a2: 200, a1 + a2 = 203
    생성하여 저장하시겠습니까? 1.진행,2.중단 후 저장파일 확인 : 1
    쓰기 완료
    생성하여 저장하시겠습니까? 1.진행,2.중단 후 저장파일 확인 : 2
    a1: 1, a2: 200, a1 + a2 = 201
    a1: 2, a2: 200, a1 + a2 = 202
    a1: 3, a2: 200, a1 + a2 = 203
    a1: 4, a2: 200, a1 + a2 = 204
    생성하여 저장하시겠습니까? 1.진행,2.중단 후 저장파일 확인 :

     

    그리고 저금통 문제 와 중간 평가를 보았습니다.

    중간 평가에 경우 확인해보지는 않았지만, 한 문제는 정확히 틀렸습니다.

    틀린 문제가 접근제한자 중 문법적으로 클래스에 선언을 할 수 없는 접근 제한자는 무엇인지 고르는 것였는데,

    순간 생각이 많았던 것인지... protected 를 클래스에 선언할 수 있지 않나? 라는 생각이 계속 들어 틀렸습니다

    15일차 때 적었던 글이 생각이 안나고 ppt를 만들어서 작성했던 기억이 떠올라 순간 헷갈렸던 것 같습니다.

    protected 는 상속관계에 있는 클래스에서 자식클래스 에게 공개하겠다는 의미입니다.

    즉 메서드와 멤버변수에만 사용할 수 있는 접근 제한자 입니다.

     

    저금통 문제는 철수가 1일차에 100원을 저금하고 그 이후로는 전날 저금한 금액에 3배를 저금한다고 하였을 때

    30일차에는 얼마가 되어있는지 구하는 문제였습니다. 조건은로는 BigInteger 사용 금지이며, 자료형은 Int, 혹은 Long로 제한 하셨습니다.

    저의 경우 리스트를 이용하여 인덱스의 값이 10이상이라면 /10, %10 을 이용하여 값을 구하는 방식으로 작성하였었고, 강사님은 BankingClass을 생성하신 뒤 subString과 리스트를 이용하여 문제를 해결하셨습니다.

    그리고 해당 문제의 주 의도는 오버플로우가 발생하였을 때 해결방법을 알려주기 위해 내주셨다고 말씀해 주셨습니다.

     

    마지막으로는 앞으로 코드 작성에 있어 프레임워크를 알려주셨습니다.

    물론 다른 곳에서는 어떻게 하는지는 다를 수 있지만 현재 알려주신 규격은 상태에 따라 코드를 관리하는 형식의 코드를 알려 주셨습니다.

     

    마무리

    이제 문법에 대한 강의는 모두 끝났습니다.

    그렇다는 건 이제 실습이 주를 이룬다는 점입니다. 뭔가 설레이면서도 두렵기도 합니다. 안드로이드 스튜디오 같은 경우도 혼자 독학을 하면서 피x을 좀.......

    하지만 이번에는 쉽게 물어볼수 있고 자세히 알려주시는 강사님과, 복습을 열심히 하는 같은 동기(?) 교육생분들도 계셔서 잘 헤쳐 나갈수 있을 거라 생각합니다.

     

     

    오늘의 마음가짐 : 추후 이때를 돌아봤을 때 좀 만 더 해볼걸 이라는 생각이 안들도록 하자

Designed by Tistory.