같은 데이터 타입 또는 다른 데이터 타입의 묶음
코틀린에서의 컬렉션
IntArray, BooleanArray, DoubleArray, ByteArray..
arrayOf<String>, arrayOf<Fruit> array(1,2,"John",0.3)
Immutable Collections
List - listOf
arrayOf랑 비슷하지만 더 많은 연산 메서드 도우미가 있음.
Set-setOf
Mutable Collections
package eu.tutorials.kotlinbasics
fun main() {
val numbers: IntArray = intArrayOf(1, 2, 3)
// 타입 추론
val numbers2 = intArrayOf(1,2,3)
// 더 간단한 방법
val numbers3 = arrayOf(1,2,3)
// Array의 주소로 저장된 위치가 출력됨
println(numbers)
// array 값 출력
println("initial values: ${numbers3.contentToString()}")
for(i in numbers3){
// 2를 더하는건 오버라이딩 한게 아니라 단지 디스플레이만 한것
print("${i+2} ")
}
print("\n")
// 인덱스로 접근, 1출력
println(numbers3[0])
// 값 변경
numbers3[0] = 200
numbers3[1] = 100
println("initial values: ${numbers3.contentToString()}")
// 배열은 고정된 크기이므로, 크기를 키우거나 새로운 인덱스를 추가할 수 없음.
// 에러: ex)numbers[7] = 200
val fruits = arrayOf(Fruit("Apple", 2.5), Fruit("Grape", 3.6))
println(fruits.contentToString())
for (idx in fruits.indices) { // indices는 인덱스를 알려줌
print("${fruits[idx].name} is in index $idx")
}
for (fruit in fruits){
print(" ${fruit.name}")
}
val mix = arrayOf("Sun", "Mon", 1, 2, 3, Fruit("Apple", 2.5))
print(mix.contentToString())
//arrayOf의 묘미는 다양한 데이터 타입을 쓸 수 있는것
}
data class Fruit(val name: String, val price: Double){
}
리스트는 하나의 데이터 타입과 커스템 객체 또는 클래스 모두 저장할 수 있음
새로운 값이 추가되면서 크기도 바뀔 수 있음.
Mutable, Immutable 타입이 있음.
fun main(){
val months = listOf("Jan", "Feb", "Mar")
val anyTypes = listOf(1, 2, 3, true, false, "String")
println(anyTypes.size)
println(months[1])
for (month in months){
println(month)
}
// Immutable
// Mutable로 변경
val additionalMonths = months.toMutableList()
val newMonths = arrayOf("April", "May", "June")
additionalMonths.addAll(newMonths)
additionalMonths.add("July")
val addMonths = listOf("August", "Sep", "Oct", "Nov", "Dec")
additionalMonths.addAll(addMonths)
//println(additionalMonths)
// Mutable 리스트 생성
val days= mutableListOf<String>("Mon", "Tue", "Wed")
days.add("Thus")
// val 오버라이딩
days[2] = "Sun"
days.removeAt(0)
// 다 삭제
days.removeAll(days)
// 특정 리스트 삭제
val removeList = mutableListOf<String>("Mon", "Thus")
days.removeAll(removeList)
print(days)
}
중복되는 데이터를 삭제하는 컬렉션
Unordered
package eu.tutorials.kotlinbasics
fun main(){
val fruits = setOf("Orange", "Apple", "Grape", "Apple", "Mango")
// 중복으르 제거해주기 때문에, Apple이 삭제되고 사이즈는 4가 됨.
//print(fruits.size)
// 알파벳 순서로 정렬
fruits.toSortedSet()
val newFruits = fruits.toMutableList()
newFruits.add("Water Melon")
print(newFruits)
print(newFruits.elementAt(4))
// Map: key-value로 저장, key는 유니크하고, value 하나 가질 수 있음. value가 객체도 올 수 있음
val daysOfTheWeek = mapOf(1 to "Monday", 2 to "Tuesday", 3 to "Wednesday")
// 2 는 인덱스가 아니라, key
print(daysOfTheWeek[2])
for (key in daysOfTheWeek.keys) {
print("$key is to ${daysOfTheWeek[key]}")
}
val fruitsMap = mapOf("Favorite" to Fruity("Grape", 2.5), "Ok" to Fruity("Apple", 1.0 ))
// Mutable List로 변경
val newDayOfWeek = daysOfTheWeek.toMutableMap()
newDayOfWeek[4] = "Thursday"
newDayOfWeek[5] = "Friday"
print("\n")
// key에 의해 정렬됨
print(newDayOfWeek.toSortedMap())
}
data class Fruity(val name: String, val price: Double)
동적 배열을 생성하는 것. 배열은 컬렉션의 일종이니, 컬렉션 사용할 것.
왜 ArrayList를 사용할까?
동적 배열을 사용하기 때문에, 필요에 따라 크기가 증가 또는 감소할 수 있음.
read용 write용 둘다 가능
삽입 시퀀스 순서를 따름.
동기화되지 않아, 중복된 요소를 가질 수 있음.
Constructor of ArrayList
// Empty ArrayList
ArrayList<E>()
// 특정 Capacity
ArrayList(capacity: Int)
//채워질 컬렉션 지정
ArrayList(elements: Collection<E>)
// Add
open fun add(element: E): Boolean
// Clear
open fun clear()
// return at specific index
open fun get(index: Int): E
// remove
open fun remove(element: E): Boolean
// val -> <String>은 바꿀수없는데 요소들은 바꿀수있음
val arrayList = ArrayList<String>()
//ex
val arrayList: ArrayList<String> = ArrayList<String>(5)
val list: MutableList<String> = mutableListOf<String>()
list.add("One")
list.add("Two")
arrayList.addAll(list)
//iterator는 array 그 자체
val itr = arrayList.iterator()
while (itr.hasNex()){
println(itr.next())
}
println(arrayList.get(1)) // "Two"
람다 or 람다 표현식: 이름이 없는 함수
람다 표현식과 익명의 함수는 '함수 리터럴'. 선언되지 않고 바로 표현식으로 전달된 함수
람다는 중괄호로 정의되고, 매개변수와 함수 바디로 변수를 받음. 매개변수로 변수를 받아도 되지만 꼭 그런건 아님
고급 기능을 가진 코드를 간결하고 짧게 정리해줌
// Int를 리턴받는다고 정의했으니까( -> Int) , Int를 리턴해야됨 ( Int = .. )
val sum: (Int, Int) -> Int = {a: Int, b: Int -> a+b}
println(sum(10,5))
// 더 짧게
val sum = {a: Int, b: Int -> println(a+b)}
sum(10,5)
정의: 코틀린에서 클래스, 인터페이스, 메서드, 프로퍼티의 사용을 제한하는 데 사용하는 키워드
public modifier
public class Example {}
class Demo {
}
public fun hello()
fun demo()
public val x = 5
val y = 10
Private Modifier
// class Example은 파일 안에서 접근 가능
private class Example {
// val x, fun doSomething()은 class Example 안에서만 접근 가능
// Example 객체를 만들어도 접근 불가
private val x = 1
private doSomething(){
}
}
Internal Modifier
internal class Exmaple{
internal val x = 5
internal fun getValue() {
}
}
internal val y = 20
}
Open keyword
Protected Modifier
open class Base{
protected val i = 10
}
class Derived : Base() {
// Base로 상속받았으니까, 변수 i를 쓸 수 있는 것.
fun getValue(): Int {
return i
}
}
// 오버라이딩 protected 타입을 오버라이딩한 예시. open protected
open class Base{
open protected val i = 5
}
class Another : Base() {
fun getValue() : Int {
return i
}
// 이렇게 뭔가 입력하고 싶으면 키워드 open을 추가해야 됨
override val i = 10
}
open class Base() {
val 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,e() of the Base class are visible
// b is not visible
override val c = 9 // b.c c is protected and open
}
fun main(args: Array<String>) {
// base.a and base.d are visible
// base.b and base.c and base.e() are not visible (c, e()는 protected 이므로, 같은 클래스 또는 파생된 클래스에서만 사용 가능)
val base = Base()
// derived.c is not visible. 오버라이딩 했지만 여전히 protected이기 때문에
val derived = Derived()
}
중첩 클래스: 다른 클래스 안에 생성된 클래스
class OuterClass{
//outer class code
private var name: String = "Mr X"
class NestedClass {
// nested class code
var description: String = "code inside nested class"
private var id: Int = 101
fun foo() {
// print("name is ${name}") // cannot access the outer class member
println("ID is ${id}")
}
}
}
fun main(args: Array<String>) {
// nested class must be initialized
println(OuterClass.NestedClass().description) // accessing property
var obj = OuterClass.NestedClass() // object creation
obj.foo() // access member function
}
// Output: code insde nested class
Id is 101
내부 클래스: inner 키워드와 함께 다른 클래스 안에 생성된 클래스
class OuterClass{
//outer class code
private var name: String = "Mr X"
inner class InnerClass {
// nested class code
var description: String = "code inside nested class"
private var id: Int = 101
fun foo() {
print("name is ${name}") // access the private outer class member
println("ID is ${id}")
}
}
}
fun main(args: Array<String>) {
println(OuterClass.NestedClass().description) // accessing property
var obj = OuterClass.NestedClass() // object creation
obj.foo() // access member function
}
// Output: code insde nested class
Name is Mr X
Id is 101
Unsafe cast operator: as
EX) Nullable String(String?)은 Non-nullable string(String)으로 cast 될 수 고, 이는 예외 에러를 발생시킴.
fun main(args: Array<String>){
val obj:Any? = null
val str: String = obj as String
println(str)
}
// Output: Exception in thread "main" kotlin. TypeCastException: null cannot be cast to non-nullable type.
Any 타입의 정수 값을 String 타입으로 캐스트 하는 것은 ClassCastException 발생
val obj: Any = 123
val str: String = obj as String
Nullable for Casting to work
fun main(args: Array<String>){
val obj: Any? = "String unsafe cast"
val str: String? = obj as String? // works
println(str)
}
Safe cast operator: as?
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
Throwable Class
throw MyExceptioin ("this throws an exception")
4개 키워드
try
catch
finally
throw
Unchecked Exception
Checked Exception
try catch
try{
// code that may throw the exception
} catch(e: SomeExceptioin){
.. code that handles the exception
}
Example without exception handling (예외처리 없는 경우)
val str = getNumber("10") // The variable "str" is getting the int value of "10"
println(str)
fun getNumber(str: String): Int {
return try{
Integer.parseInt(str)
}
catch(e: ArithmeticException){
0
}
}
//Output: 10
Example with exception handling
val str = getNumber("10.5") // The variable "str" is getting the int value of "10.5"
println(str)
fun getNumber(str: String): Int {
return try{
Integer.parseInt(str)
}
catch(e: ArithmeticException){
0
}
}
//Output: 0 (Catch Block)
Multiple catch Blocks
fun main(args: Array<String>) {
try{
val a = IntArray(5)
a[5] = 10 / 0
} catch(e: ArithmeticException) {
println("arithmetic exception catch"
} catch(e: ArrayIndexOutOfBoundsException) {
println("array index outofbounds exception")
} catch(e: Exception) {
println("parent exception class")
}
println("code after try catch")
}
//Output: arithmetic exception catch
// code after try catch
Nested try-catch block
try{
// code block
try {
// code block
}catch(e: SomeException){
// exception
}
} catch(e: SomeException){
// exception
}
Finally Block
fun main(args: Array<String>) {
try{
val data = 10 / 5
println(data)
} catch(e: NullPointerException) {
println(e)
} finally{
println("finally block always executes")
}
println("below code..")
}
// output
// 2
// finally block always executes
// below code..
fun main(args: Array<String>) {
validate(15)
println("code after validation check..")
}
fun validate(age: Int) {
if (age < 18)
throw ArithmeticException("Under age")
else
println("Eligible for drive")
}
// Output: Exception in thread "main" java.lang.ArithmeticException: under age