일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- useReducer
- Common JS 모듈 시스템
- useMemo #React.memo #최적화 #re-rendering
- Kotlin
- Node.js #
- 패키지
- React #Context #props drilling #useMemo
- React #React 사용하는 이유
- useCallback #최적화 #함수형 업데이트
- React #API 호출 #async #await #fetch
- Today
- Total
세현's 개발로그
Kotlin 개발 완전 정복(2) 본문
#1 컬렉션 개요
◎ 컬렉션은 단순히 같은 데이터 타입 또는다른 데이터 타입의 묶음이다.
코틀린에서 컬렉션은 두 가지 분류로 나뉜다.
ⓛ특정 데이터 타입의 요소를 저장하는 클래스
ex)
- IntArray-Integer
- BooleanArray-Boolean
- DoubleArray-Double
- ByteArray-Byte
- LongArray-Long
- ShortArray-Short
- FloatArray-Float
②서로 다른 타입의 요소도 저장 가능한 클래스
ex)
- arrayOf<String>
- arrayOf<Fruit>
- array(1,2,"John","Doe",0.5,Fruit())
◎ Immutable Collections : 이뮤터블은 값을 읽을 수는 있지만 변경할 수 없다는 것이다.
- List-listOf : List는 arrayOf랑 비슷하지만, 더 많은 연산 메서드 도우미가 있다. 또한 필요시 크기도 쉽게 키울 수 있다.
- Set-setOf : Set는 중복되는 값이 없게 하는 클래스이다.
- Map-mapOf : Map는 key와 값이 한 쌍으로 정리되는데, 이 키로 값을 찾을 수 있다.
◎ Mutable Collections : list, set, map을 읽고 기재하기 좋은 특별한 클래스들이다. 이런 방법으로, 공개적으로 수정할 수 있는 요소와 비공개 요소를 분리할 수 있다.
- Mutable List - ArrayList, arrayListOf, mutableListOf
- Mutable Set - mutableSetOf, hashSetOf
- Mutable Map - Hashmap, hashMapOf, mutableMapOf
#2 리스트
◎ 같은 정수 리스트를 표현하는 방법 세 가지
val numbers: IntArray = intArrayOf(1, 2, 3, 4, 5, 6)
val numbers = intArrayOf(1, 2, 3, 4, 5, 6)
val numbers = arrayOf(1, 2, 3, 4, 5, 6)
◎ 리스트의 요소를 출력하는 방법
val numbers = arrayOf(1, 2, 3, 4, 5, 6)
print(numbers.contentToString()) // 출력은 [1, 2, 3, 4, 5, 6]
for (element in numbers) {
print(element) // 출력은 123456
}
◎ 리스트의 특정 요소를 출력하는 방법
val numbers = arrayOf(1, 2, 3, 4, 5, 6)
print(numbers[0]) // 출력은 1
#3 집합과 맵
◎ 세트는 중복되는 데이터를 삭제하는 컬렉션이다. 이뮤터블 클래스는 setOf, 뮤터블 타입은 mutableSetOf 이고, hashSetOf이 있다.
val fruits = setOf("Orange", "Apple", "Mango", "Grape", "Apple", "Orange") //immutable
print(fruits.size) // 중복되는 원소를 중복 제거하였을 때 총 원소의 개수는 4개이므로 4가 출력된다.
print(fruits.toSortedSet()) // 알파벳 순으로 정렬하여 출력은 [Apple, Grape, Mango, Orange]
val newFruits = fruits.toMutalbleList()
newFruits.add("Water Melon")
newFruits.add("Pear")
print(newFruits) // 출력은 [Apple, Grape, Mango, Orange, Water Melon, Pear]
◎ 맵은 키와 값을 짝 형태로 데이터를 저장하는 컬렉션이다. 키는 하나의 값만 저장할 수 있다.
val daysOfTheWeek = mapOf(1 to "Monday", 2 to "Tuesday", 3 to "Wednesday")
print(daysOfTheWeek[2]) // 출력은 Tuesday
for(key in daysOfTheWeek.keys){
print("$key is to ${daysOfTheWeek[key]} ") // 출력은 1 is to Monday 2 is to Tuesday 3 is to Wednesday
}
#4 배열 리스트(Array List)
◎ 배열 리스트는 동적 배열을 생성하는 것이며, 컬렉션의 일종이다.
- 배열 리스트는 동적 배열을 만들어주므로 크기가 특정 크기에 제한되지 않는다.
- 배열 리스트는 읽기용과 쓰기용으로 둘 다 가능하다.
- 배열 리스트는 삽입 시퀀스 순서를 따른다. 뭔가를 추가할 때 중요한 부분이다.
- 배열 리스트는 동기화되지 않아 중복 요소를 허용한다. 즉, 같은 값을 입력하는 것은 제한되지 않는다.
◎ 배열 리스트 생성자
- ArrayList<E>() : 비어 있는 배열 리스트를 만들 때 사용되는 생성자
- ArrayList(capacity: Int) : 용량을 정할 수 있는 생성자 즉, 요소의 최대량을 정할 수 있는 것이다.
- ArrayList(elements: Collection<E>) : 컬렉션을 기반으로 배열 리스트를 생성할 수 있다. 컬렉션 요소로 채우고 필요할 때 사용 가능
◎ 배열 리스트의 함수
- open fun add(element: E): Boolean : add 함수는 특정 요소를 컬렉션에 추가 가능
- open fun clear() : clear 함수는 컬렉션에서 모든 요소를 제거함
- open fun get(index: Int): E : get 함수는 특정 인덱스값의 정보를 돌려줌
- open fun remove(element: E) : Boolean : remove 함수는 컬렉션에서 특정 요소의 한 예시를 제거함
#5 람다식
◎ 람다 표현식은 고급 기능을 가진 코드를 간결하고 짧게 정리해준다.
◎ 람다 표현식과 익명 함수는 '함수 리터럴'이다. 예를 들어 선언되지 않고 곧바로 표현식으로 전달된 함수이다.
◎ 람다는 중괄호로 정의되고, 매개변수와 함수 바디로 변수를 받는다. 매개변수로 변수를 받아도 되지만, 꼭 그런 것은 아니다.
◎ 함수 바디는 변수 뒤에 화살표와 연산자와 함께 쓰인다.( -> 이것이 람다 연산자)
◎ 문법 : { 변수 -> 람다 바디}
sum1: (Int, Int) -> Int = { a: Int, b: Int -> a + b }
println(sum1(10, 5))
// 더 짧게 표현 가능
val sum2={a:Int,b:Int->println(a+b)}
sum2(10,5)
#6 접근 제한자
◎ 접근 제한자는 코틀린에서 클래스, 인터페이스, 프로퍼터를 제한하는 데 사용하는 키워드이다. 접근 제한자는 클래스 헤더나 메소드 바디 등 여러 곳에서 사용된다.
◎ public
- 공개적으로 수정된 요소는 프로젝트 어디서든 접근 가능하다.
- 코틀린에서 기본 제한자이고, 따로 명시되지 않는다면 요소는 자동으로 공개이다.
◎ private
- 이는 프로퍼터, 필드 등이 선언된 블록에서만 요소에 접근할 수 있게 해준다. 이는 최상위에 선언된다.
- private 제한자 선언은 스코프 밖으로의 접근을 막는다. 따라서 private 패키지는 그 특정 파일 내에서만 접근 가능하다.
◎ internal
- internal 제한자는 자바에 없는 코틀린만의 기능이다.
- internal 제한자는 시행된 모듈 안에서만 필드가 보이게 된다.
◎ open keyword
- 코틀린에서 모든 클래스는 자동으로 최종값이다. 즉, 자동으로 상속받을 수 없는 것이다. (자바랑은 반대-모든 클래스가 상속할 수 있기 때문에 최종이라고 명시해야 함)
- 상속을 사용하려면, 클래스를 open으로 만들어야 한다. 아니면 오류가 난다.
◎ protected
- protected 제한자는 그 안의 클래스 또는 서브 클래스에 보이도록 해준다. 서브 클래스 안의 오버라이딩 한
protected 선언은 변경을 명시하지 않는 한 보호받는다.- protected 제한자는 최상위에 선언될 수 없다. 즉, 패키지는 보호받을 수 없다.
open class Base(){
var a=1 //public by default
private var b=2 //private to Base class
protected open val c=3 //visible to the Base and the Derived class
internal val d=4 //visible inside the same module
protected fun e(){} //visible to the Base and the Derived class
}
class Derived: Base(){
//a,c,d,and e() of the Base class are visible
//b is not visible
override val c=9//c is protected
}
fun main(args: Array<String>){
val base=Base()
//base.a and base.d are visible
//base.b, base.c and base.e() are not visible
val derived=Derived()
//derived.c is not visible
}
#6 중첩, 내부 클래스
◎ 다른 클래스 안에 생성된 클래스 vs 키워드 inner를 사용한 다른 클래스 안의 클래스
◎ 중첩 클래스 : 다른 클래스 안에 생성되어 자동으로 정적이다.
- 그 데이터 멤버와 멤버 함수는 클래스 객체를 생성하지 않고도 접근할 수 있다.
- 또한 중첩 클래스는 외부 클래스의 데이터 멤버에 접근할 수 있다. (일방적인 관계)
◎ 내부 클래스 : 키워드 inner로 다른 클래스 안에 만들어진 클래스이다.
- 중첩 클래스와 차이점은 내부 클래스는 인터페이스 안에 또는 내부 중첩 클래스가 아닌 곳에 선언될 수 없다는 것이다.
- 장점은 private이더라도 외부 클래스 멤버에 접근 가능하다.
- 내부 클래스는 외부 클래스 객체의 참조를 저장한다.
class OuterClass{
private var name: String="Mr X"
inner class InnerClass{
var description:String="code inside inside class"
private var id: Int=101
fun foo(){
println("name is ${name}") //외부 클래스의 멤버가 private이지만 접근 가능하다. (중첩 클래스에서는 불가능)
println("Id is ${id}")
}
}
}
fun main(args:Array<String>){
println(OuterClass().InnerClass().description) //내부 클래스의 프로퍼터에 접근 가능
var obj=OuterClass().InnerClass() //객체 생성
obj.foo() //멤버 함수에 접근
}
출력 :
code inside inside class
name is Mr X
Id is 101
#7 Safe Cast, Unsafe Cast 연산자
◎ 특정 타입의 것을 다른 타입으로 캐스트할 때 사용
◎ Unsafe cast
- 키워드 as가 사용된다.
- 어떤 때는 변수를 캐스트하지 못하고 예외 처리된다. 그것이 바로 불완전 캐스트이다.
fun main(args: Array<String>){
val obj:Any?=null
val str: String=obj as String
println(str)
}
출력 :
Exception in thread "main" java.lang.NullPointerException: null cannot be cast to non-null type kotlin.String
- 물음표가 있는 널러블 스트링은 널러블 스트링이 아닌 걸로 캐스트될 수 없다. 이는 예외 처리된다.
- 예시에서 any 널러블 타입의 객체의 값이 null로 되어있는데, obj 객체를 스트링으로 캐스트하고, 만든 스트링을 출력하려 하니까 예외 처리가 된다.
◎ Safe cast
- 키워드 as?가 사용된다. 이는 한 타입으로 안전하게 캐스팅 하도록 도와준다. 불가능하다면, null만 돌려준다.
fun main(args: Array<String>){
val location: Any="Kotlin"
val safeString: String?=location as?String
val safeInt: Int?=location as?Int
println(safeString) // 출력은 Kotlin
println(safeInt) // 출력은 null
}
- safeInt는 int 널러블이고 location을 정수로 받으려고 한다. 하지만 "Kotlin"은 정수가 될 수 없기 때문에 안전한 캐스팅이 되어 null이 출력된다.
#8 Try-Catch 문으로 예외 처리하기
◎ Exception이란?
: 프로그램의 런타임 문제고, 프로그램의 종료를 초래한다. 핸드폰에서는 앱이 반응하지 않는 것이다.
예를 들어, 저장 공간 부족, out of bound 배열, 0으로 나눈 조건이 있다.
-> 프로그램 실행에서 이런 문제를 처리하기 위해 예외 처리를 한다. 이는 런타임 문제를 처리하고 프로그램의 원활한 실행을 지속시켜 준다.
◎ 예외 처리에서 4개의 키워드 : try, catch, finally, throw
- try : try 블록은 예외를 발생시킬 수 있는 구문 세트를 포함한다. catch나 finally, 아니면 둘 다 꼭 뒤에 따라와야 한다. 이는 더 많은 오류, 예외를 만들 수 있는 코드이다. 예를 들어, 인터넷 연결이나 배열 검토하는 것.
- catch : catch 블록이 try 블록에서 던져진 예외를 잡는 것이다. try 블록에 예외가 있으면, catch 블록이 실행되고 아니면 실행되지 않는다. 예를 들어, 인터넷이 연결되지 않으면 catch 블록이 실행된다.
- final : final 블록은 예외가 처리되든지 말든지 실행된다. 그래서 중요한 코드 구문을 실행하는 데 사용된다. 예로는 인터넷 연결을 처리하는 버퍼를 닫을 때 실행된다.
- throw : 이는 명료하게 예외를 던지게 해준다. 이는 오류를 일으키기 위해 입력하는 것이다. 오류가 어디서 나는지 테스트할 때 매우 유용하다.
◎ Unchecked Exception
- Unchecked 예외는 코드 실수 때문에 던져지는 예외이다.
- Unchecked 예외는 실행 버튼을 눌러 앱을 컴파일할 때가 아닌, 앱이 실행되는 런타임에 확인된다. 이는 런타임 예외 클래스에서 확장한 것이다.
ex)- Arithmetic exception : 숫자를 0으로 나눴을 때 발생함.
- ArrayIndexOutOfBoundExceptions : 틀린 인덱스 값으로 배열을 확인할 때 발생함.
- SecurityException : 보안 위반일 때 발생함. 예를 들어, GPS를 사용하려 하는데, GPS 기능을 사용할 권리를 주지 않아 접근할 수 없을 때
- NullPointerException : Null Pointer Exception은 null 객체에 메소드나 프로퍼터를 호출할 때 발생함.
◎ Checked Exception
- Checked Exeption은 컴파일 타임에 확인되는 예외이다. 이는 Throwable 클래스로 확장된다. Throwable 클래스는 예외 함수를 처리한다.
ex)- IOException- SQLException
◎ try catch : 코드에서 예외 처리에 사용된다.
- 문법 :
try{
//code that may throw the exception
}catch(e:SomeException){
//code that handles the exception
}
- 예시 :
fun main(){
val str=getNumber("10.5")
println(str)
fun getNumber(str: String):Int{
return try{
Integer.parseInt(str)
}catch (e:ArithmeticException){
0
}
}
} // 출력은 0
◎ Nested try-catch block
- 중첩된 try-catch 블록은 코드 블록이 예외를 발생시키거나 블록 내의 다른 코드가 예외를 발생시킬 때 nested try-catch 블록이 필요하다.
- 문법 :
try{
//code block
try{
//code block
}catch (e:SomeException){
//exception
}
}catch (e:SomeException){
//exception
}
◎ finally Block : 예외가 처리되든 말든 실행되는 블록이다.
- 문법:
try{
//code block
}catch (e:SomeException){
//exception
}finally {
//code block
}
◎ throw keyword : 분명한 예외를 던지는 데 사용된다.
- 커스텀 예외를 던지는 데도 사용된다.
- 코드가 올바르게 됐는지 확인하고 싶을 때 매우 유용하다. 코드를 고장 낼 오류를 던져서 문제 발생 원인을 이해한다.
현실에서는 앱을 확인할 대 필요하다. 사용자들이 할 수 있는 잠재적인 잘못된 입력값 또는 데이터를 인터넷 등에서 받았을 때 발생할 수 있는 문제를 확인하는 데 필요하다.
- throw 구문은 앱이 고장나게 하므로 많은 throw 구문이나 오류를 가진 앱을 출시하지 말아야 한다.
'Kotlin' 카테고리의 다른 글
코틀린-퀴즈 앱 (0) | 2022.11.03 |
---|---|
XML 사용법과 UI 생성법 배우기 (0) | 2022.10.31 |
Kotlin 개발 완전 정복(1) (0) | 2022.09.27 |