일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 31 |
- C++
- python
- softeer
- 스프링
- CJ UNIT
- 코틀린
- SQL
- java
- 소프티어
- programmers
- 백준 알고리즘
- 문제풀이
- 정보처리산업기사
- MYSQL
- BFS
- kotlin
- 코딩봉사
- 프로그래머스
- 파이썬
- 공부일지
- 백준
- 1과목
- 코딩교육봉사
- 시나공
- 자바
- 백준알고리즘
- 데이터베이스
- 알고리즘
- SW봉사
- 회고
- Today
- Total
JIE0025
[Kotlin] 코틀린 기초 본문
✅ Hello World
가장 기본적인 Hello World를 출력하는 코드를 작성해보았다.
fun main (args: Array<String>) {
println("hello world");
}
- 함수 선언시 fun을 사용한다.
- 파라미터 뒤에 타입을 써준다. args:Array<String>
- 함수를 최상위 수준에 정의할 수 있다. (클래스 안에 넣어야 할 필요가 없다)
- 배열은 일반 클래스와 마찬가지(?) 자바와 다르게 코틀린에선 배열처리를 위한 문법이 존재하지 않는다.
- System.out.println을 println으로 사용한다. 자바 표준라이브러리 함수를 간결하게 사용할 수 있도록 래퍼를 제공한다.
- 세미콜론은 써도 되고, 안써도 된다.
✅ 함수의 정의
본문이 증괄호로 둘러싸인 함수 (블록이 본문인 함수)
fun max(num1: Int, num2: Int): Int {
return if (a > b) a else b
}
본문이 등호와 식으로 이뤄진 함수 (식이 본문인 함수)
fun max(num1: Int, num2: Int): Int = if (a > b) a else b
✔️ 반환타입 생략 가능
fun max(num1: Int, num2: Int) = if (a > b) a else b
✅ 변수
변수 선언 방식에는 두가지가 있다. (val, var)
1. 변경 불가능한 변수 val
value에서 유래함. immutable 변경 불가능한 참조를 저장한다. (자바로 보면 final에 해당한다.)
val languages = arrayListOf("Java")
languages.add("Kotlin")
과 같이 languages에 존재하는 reference는 변하지 않지만, 가리키는 객체의 내부 값은 변경될 수 있다.
2. 변경 가능한 변수
variable에서 유래함. mutable 변경 가능한 참조이다. (자바로 보면 일반 변수에 해당한다.)
var 로 선언한 변수는 타입을 지정하지 않아도, 타입추론을 한다.
또 변경가능한 참조이기 때문에 값을 변경할 수 있다.
단, 변수의 타입은 고정되어 변하지 않는다.
* 기본적으로는 모든 변수를 val 키워드를 사용해 불변 변수로 선언하고, 나중에 꼭 필요할 때에만 var로 변경하라. val 변수는 블록을 실행할 때 정확히 한 번만 초기화돼야 한다. 하지만 조건에 따라 val 값을 다른 여러 값으로 초기화할 수도 있다
라는 이야기가 있어서 긁어와봤는데 아직 확실하게 와닿지는 않는다.
🤔 val 과 var이 단순히 불변과 가변의 차이로만 이해할 수 있는게 맞을까?
아까 오전에 공부를 하면서 한가지 의문이 발생했다.
👩💻 상황 가정
자바에서 String name = "jieun" ;을 선언했다고 가정하자.
"jieun"이라는 문자열은 힙메모리에 생겨날것이고, 해당 주소값이 스택공간 name 변수에 들어갈것이다.
이때 name = "eunji";를 추가하면
힙메모리공간에 "eunji"가 생겨나고, 해당 주소가 name 변수로 연결, "jieun"은 힙메모리에 남은 상태가 될것이다.
결국 String은 불변객체아닌가?라는 생각이 들었고....
그러면 val로만 선언을 해야하는것인가?
심지어 기본적으로는 모든 변수를 val 키워드를 사용해 불변 변수로 선언한다고 되어있어서.. 헷갈리기 시작했다.
(기본적인 코드 연습에선 충분히 변수의 값이 변경될 가능성이 높지만, 실무에서는 또 값이 안변할수도 있는거 아닌가..? 라는 생각도 들고...)
만약 위에 가정한 상황을 코틀린으로 구현한다면 객체 내부에 val을 사용했을때 문자열 변경이 불가능하기 때문에, 컴파일 오류가 발생할것이다.
var를 쓰고, setter프로퍼티로 값이 변경될도록 할 수 있다.
class Person {
var name: String = ""
}
val person1 = Person()
person1.name = "Hong" // 값을 변경할 수 있음
문자열에 대해선 특히 val를 쓸지, var를쓸지 더욱더 고민이 되는것 같다.
String하나에 대해서도 고민인데, StringBuilder와 StringBuffer도 동일하게 고민하면 되는건지 .... 이런저런 생각에 머리가 아프다.
추가적으로 알게되는 부분이 있으면 계속 생각을 해봐야할것 같다.
✅ 문자열 템플릿
문자열 리터럴의 필요한 곳에 변수를 넣되, 변수 앞에 $표시를 추가해주면 된다.
달러 모양을 사용하면 변수의 값을 가져와서 문자열더하기(+)를 할 필요없이 쉽게 출력이 가능하다.
fun printName() {
val name = "Kotlin"
println("Hello, $name")
}
문자열 안에서 $자체를 사용하고 싶다면, \를 함께 사용해야한다. "\$"
✅ 프로퍼티
필드와 접근자(getter setter) 를 한데 묶어 프로퍼티라고 부른다.
코틀린은 프로퍼티가 기본 기능으로 제공되어, 자바의 필드와 접근자메소드를 완전히 대신한다.
class Person (
val name: String //읽기만 가능한 프로퍼티 - 비공개 필드, 공개 게터를 만들어낸다.
var isMarried: Boolean //쓰기가 가능한 프로퍼티 - 비공개 필드, 공개 게터/세터를 만들어낸다.
)
* 코틀린의 기본 가시성은 public이다 (public으로 정의할 땐 생략이 가능하다)
* 자바에서 getter, setter 가 존재하는 클래스를 코틀린에서 사용할경우,
getName(), setName() -> name이라는 프로퍼티를 사용해서 접근이 가능하다.
✅ 디렉터리, 패키지
코틀린에서는, 클래스 import, 함수 import에 차이가 없다.
즉 모든 선언을 import 문을 통해 가져온다는것이다.
최상위 함수(클래스에 종속적이지 않은)의 경우, 이름을 사용해 import가 가능하다.
package geometry.example
import geometry.shapes.createRandomRectangle // 이름으로 함수 임포트하기
fun main(args: Array<String>) {
println(createRandomRectangle().isSquare) // "true"가 아주 드물게 출력된다.
}
✅ 선택 표현과 처리 enum, when
when : 자바의 switch를 대체하는 프로그래밍 요소이다.
👩💻enum
열거형, 상수값을 가지는 타입
enum class Direction {
NORTH, SOUTH, EAST, WEST
}
fun main() {
val dir : Direction = Direction.NORTH
println(dir) // NORTH
}
enum도 프로퍼티를 갖고, 함수를 가질 수 있는데
함수형프로그래밍에서 return문에 if/when과 같은 제어구문이 추가될 수 있는 예제코드이다.
enum class Color (
val r: Int, val g:Int, val b:Int
)
{
RED(255,0,0), GREEN(0,255,0), BLUE(0,0,255);
fun printMyName(): String {
return if (r == 255) "RED"
else if (g == 255) "GREEN"
else if (b == 255) "BLUE"
else "UNKNOWN"
}
}
fun main() {
val redColor: Color = Color.RED
println(redColor.printMyName())
}
👩💻when
자바의 switch를 대체하는 프로그래밍 요소이다.
when을 이용해 패턴 매칭을 할 수 있다.
위의 if문이 들어간 예제를 when으로 대체해보자.
when문에서 this를 사용해, 해당 enum의 타입에 따라 반환하는 문자열이 달라진다.
패턴매칭구문 : -> 연산자를 사용해 패턴과 결과를 매칭할 수 있다.
enum class Color (
val r: Int, val g:Int, val b:Int
)
{
RED(255,0,0), GREEN(0,255,0), BLUE(0,0,255);
fun printMyName(): String {
return when(this) {
RED -> "RED"
GREEN -> "GREEN"
BLUE -> "BLUE"
}
}
}
fun main() {
val redColor: Color = Color.RED
println(redColor.printMyName())
val ivoryColor: Color? = null
println(ivoryColor?.printMyName()) // 출력: null
}
✍️ 코틀린 함수 특징을 기억하며 간단하게 리팩토링
return문을 생략하고, =으로 대체할 수 있으며
타입추론으로 반환타입의 생략이 가능하다는 점에서 아래처럼 리팩토링도 가능하다.
fun printMyName() = when(this) {
RED -> "RED"
GREEN -> "GREEN"
BLUE -> "BLUE"
}
✅ while, for루프로 대상을 이터레이션(반복) 하자
1️⃣ while문 (자바와 동일하게 작성하면 된다.)
fun main() {
var i: Int = 3;
while(i>0) {
println(i)
i--
}
}
2️⃣ for문
자바의 foreach 형태만 존재한다.
✍️ 역방향 수열 생성하기
downTo : 어디까지 감소시켜라
step : 간격의 지정
👩💻 10으로시작해 0까지 2씩 감소하도록하는 예제
-> 0까지 포함한다는걸 유의하자.
fun main() {
for (i in 10 downTo 0 step 2) {
println(i)
}
}
당연히 downTo 1로 변경하면 2까지만 출력된다.
fun main() {
for (i in 10 downTo 1 step 2) {
println(i)
}
}
✍️ 정방향 수열 생성하기
.. 을 사용해서 정방향 수열도 만들수있다.
👩💻 0부터 시작해 10까지 1씩 증가시키면서 출력
fun main() {
for (i in 0..10) {
println(i)
}
}
👩💻 0부터 시작해 10까지 2씩 증가시키면서 출력
fun main() {
for (i in 0..10 step 2) {
println(i)
}
}
👍 when문과 함께 사용하기
1) .. 를 이용하여 범위를 지정한다음
2) in 해당 값이 이 안에 존재하는지 체크
fun main() {
println(check('안'))
}
fun check(c:Char): String {
return when(c){
in '0'..'9' -> "digit"
in 'a'..'z', in 'A'..'Z' -> "English"
in '가'..'힣' -> "한글"
else -> "?"
}
}
✅ 예외처리
try, catch, finally이 존재,
throw로 예외를 던질 수 있다. thows 절은 없다.
- try : 예외가 발생할수도 있는, 시도해볼 코드 작성
- catch : try에서 발생한 예외를 처리하는 블록
- finally : 예외가 발생하던, 안하던 무조건 실행되는 블록
- throw : 예외를 던질때 사용, 자바와 다르게 new키워드를 사용하지 않아도 예외 인스턴스를 생성할 수 있다.
한줄을 입력받고 해당 값을 정수로 변환 , 만약 변환할 수 없을 때 null리턴
fun convertToInt(reader: BufferedReader): Int? {
try {
val line = reader.readLine()
return Integer.parseInt(line)
}
catch (e: NumberFormatException) {
return null
}
finally {
reader.close()
}
}
fun main() {
// Exception 던지기
val percentage = 200
if (percentage !in 0..100) {
// 예외 인스턴스를 만들 때, new를 사용 할 필요없다.
throw IllegalArgumentException("A percentage value must be between 0 and 100: ${percentage}")
} else {
println(percentage)
}
}
fun divide(a: Int, b: Int): Int {
if (b == 0) {
throw ArithmeticException("Division by zero")
}
return a / b
}
fun main() {
try {
val result = divide(3, 0)
println("나눈 결과 = $result")
} catch (e: ArithmeticException) {
println("0으로 나눌 수 없다.")
}
}
fun divide(a: Int, b: Int): Int {
if (b == 0) {
throw ArithmeticException("Division by zero")
}
return a / b
}
fun main() {
try {
val result = divide(10, 3)
println("나눈 결과 = $result")
} catch (e: ArithmeticException) {
println("0으로 나눌 수 없다.")
}
}
🤔 왜 thows가 없을까?
자바에선 checked예외의 셩우 throws가함수에 추가되지만, 코틀린에선 checked, unchecked를 구분하지 않는다고 한다.
~~~ 복습복습! ~~~
✔️ checked 예외는 컴파일시에 반드시 예외를 처리하도록 요구하기 때문에 try-catch문을 이용하며 처리를하게 된다.
✔️ unchecked 예외는 컴파일러가 강제하지 않는 예외이다. (프로그래밍의 오류나 런타임시점에 발생하는 예외)
✍️ 체크 예외가 없다는 것에 대하여 공식문서를 확인해보자.
https://kotlinlang.org/docs/exceptions.html#checked-exceptions
코틀린은 checked 예외가 없다
왜? 이는 코틀린이 생겨난 목적에 기인한다!
Examination of small programs leads to the conclusion that requiring exception specifications could both enhance developer productivity and enhance code quality, but experience with large software projects suggests a different result – decreased productivity and little or no increase in code quality.
소규모 프로그램을 검토하면 다음과 같은 결론에 도달합니다.
예외 사양을 명시적으로 요구하면, 개발자 생산성을 향상시키고 코드 품질을 향상시킬 수 있습니다.
그러나 대규모 소프트웨어 프로젝트 경험에 따르면 다른 결과가 나타납니다.
– 생산성이 저하되고 코드 품질이 거의 또는 전혀 향상되지 않습니다.
자바에서는 checked 예외를 사용할경우 -> 메서드 시그니처에 thows절을 사용해 예외를 명시적으로 선언한다.
이를 통해 메서드 호출에서 예외처리를 명시적으로 강제(요구)하게 되는데
이러한 방식이 대규모 SW 프로젝트 경험에서는 예외처리를 강제하면서 생산성이 저하되고 품질이 향상되지않는다는 결과가 나왔다고 한다.
코틀린에서 예외처리를 개발자의 판단에 맡기면서, 명시적으로 강제하지 않아 코드가 더 간결하고 명료해질 수 있었다.
Referneces
KOTLIN IN ACTION
https://kotlinlang.org/docs/exceptions.html#checked-exceptions
https://incheol-jung.gitbook.io/docs/study/kotlin-in-action/untitled#undefined-9
https://codetravel.tistory.com/24
https://hongku.tistory.com/358
'개발 > Java, Kotlin' 카테고리의 다른 글
멀티모듈은 무엇이고 왜 사용할까 ? (0) | 2023.05.29 |
---|---|
[Kotlin] 컬렉션(Collection) (0) | 2023.05.25 |
[Kotlin] 코틀린이란 (왜 필요하고, 왜 배워야할까) (0) | 2023.05.23 |
[Java] Collection Framework (List, Queue, Set) & Map (0) | 2023.05.06 |
[Java] GC(Garbage Collection) 가비지컬렉션이란? (0) | 2023.05.05 |