코틀린에서 문법은 자바와 정말 많이 유사합니다.
일단 코틀린에서는 변수를 선언 할 때 val과 var로 선언을 합니다.
코틀린은 변수와 상수로 선언을 하고 변수의 type을 지정을 해줘도 되고 해주지 않아도 자동으로 유추하여 type에 맞게 설정됩니다.
또 코틀린은 자바와 다르게 세미콜론;이 필수가 아니기에 사용해도 되고 사용하지 않아도 됩니다.
// 상수
val a : String = "변수"
val b : Int = 1
var c : Int = 0; // 변수
c = 3
var d : Int = 1
d = "오류" // type이 다르면 재할당 불가능
코틀린은 변수를 선언 할 때 Top Level에 위치 시킬 수 있습니다.
자바와 같은 경우는 class안에 있어야 변수가 선언이 되는데 비해 코틀린은 함수 밖이나 클래스 밖에서 변수를 선언 할 수 있습니다.
var x : Int = 5
fun main() {
x+=1;
println(x)
}
일반적인 function 선언이며 매개변수와 return type을 명시해줬습니다.
fun sum(a : Int, b : Int) : Int {
return a + b
}
표현식이라는 코틀린 문법이며 마찬가지로 매개변수와 return type을 명시해줬습니다.
일반적인 function과의 차이점은 몸통 : {중괄호}가 생략되었고 return을 명시하지 않았습니다.
// 표현식
fun minus(a : Int, b : Int) : Int = a - b
표현식을 응용하면 코틀린에서 자료형을 명시하지 않고 변수를 선언 할 때 처럼 function에서 반환 타입을 명시하지 않았습니다.
// 표현식 & 반환 타입 생략
fun multiply(a : Int, b : Int) = a * b
몸통{중괄호}이 있는 함수는 반환 타입을 제거하면 컴파일 오류가 생기기에 간단한 표현식이 아니라면 몸통{중괄호}을 사용하고 꼭 반환 타입과 return을 명시해줘야합니다.
fun divide (a : Int, b : Int) : Int {
return a/b
}
반환 타입이 없는 함수는 반환 타입이 Unit이 되며 Unit은 생략 될 수 있고 정의를 하지 않아도 됩니다.
자바에서의 void와 같은 의미를 가지는것 같습니다.
// 반환 타입이 없는 함수는 Unit 반환
fun mod(a : Int, b : Int) : Unit {
println("$a % $b = ${a%b}")
}
코틀린에서는 default parameter라는 기능을 제공해줍니다.
default parameter는 function에 매개변수가 없을 때 파라미터에 값을 default 값으로 전달해주는 기능입니다.
아래 코드에서는 매개변수로 String type의 인자를 받고 값을 받지 못하면 parameter의 value는 "반갑습니다"가 넘어가게됩니다.
fun sendMessage(message : String = "반갑습니다"){
println(message)
}
fun main(){
sendMessage()
sendMessage("Hello")
}
출력::::
반갑습니다
Hello
자바에서는 default parameter를 지원해주지 않기에 아래 코드와 같이 매우 지저분한 코드가 생성이 되어 가독성이 좋지 않습니다.
public void sendMessage(String message){
if (message == null || message.length() == 0){
System.out.println("반갑습니다");
}else {
System.out.println(message);
}
}
코틀린에서는 named arguemnt라는 기능을 지원해줍니다.
named arguemnt는 function 아규먼트에 name을 지정해서 바인딩을 할 수 있게 도와주는 기능입니다.
자바에서는 named arguemnt 지원해주지 않아 아규먼트를 전달할 때 순서에 맞게 전달을 해야하는데 비해 코틀린은 순서에 맞춘 아규먼트 방식과 named arguemnt를 통한 특정 인수를 지정하는 방식 두 가지를 다 지원해줍니다.
named arguemnt와 default parameter를 모두 사용할 수 있는 코틀린 코드는 아래와 같이 매우 유용하고 가독성 좋게 사용 할 수 있습니다.
fun log(level: String = "INFO", message: String = "디버그 로그"){
println("[$level]$message")
}
fun main( ) {
log(message = "인포 로그") // message만 값 입력 - level은 default parameter가 적용
log(level = "DEBUG", "디버그 로그") // level만 값 명시, message 부분은 순서로 바인딩
log("WARN", "워닝 로그") //순서로 바인딩
log(level = "ERROR", message = "에러 로그") // 값 모두
}
※log("디버그 로그", level = "DEBUG")와 같이 순서로 level이 들어가야할 위치에
임의의 값이 들어가고 level을 다른 순서로 명시해주면 컴파일 에러가 발생
출력::::
[INFO]인포 로그
[DEBUG]디버그 로그
[WARN]워닝 로그
[ERROR]에러 로그
이 코드를 자바 코드로 변환한다면 아래와 같은 지저분한 코드가 생성이 됩니다.
public void log(String level, String message){
if (level == null || level.length() == 0){
level = "INFO";
}
if (message == null || message.length() == 0){
message = "디버그 로그";
}
System.out.printf("[%s]%s%n", level, message);
}
public static void main(String[] args) {
Logger logger = new Logger();
logger.log(null ,"인포 로그");
logger.log("DEBUG" ,null);
logger.log("WARN" ,"워닝 로그");
logger.log("ERROR" ,"에러 로그");
}
코틀린 코드와 자바 코드를 다시 비교 해보자면 아래와 같습니다.
fun log(level: String = "INFO", message: String = "디버그 로그"){
println("[$level]$message")
}
public void log(String level, String message){
if (level == null || level.length() == 0){
level = "INFO";
}
if (message == null || message.length() == 0){
message = "디버그 로그";
}
System.out.printf("[%s]%s%n", level, message);
}
코틀린과 자바의 if else는 문법적으로는 정확하게 같습니다.
하지만 코틀린의 경우 if else는 표현식으로 분리가 됩니다.
그래서 자바는 if else'문', 코틀린은 if else '식'으로 분리가 됩니다.
덕분에 kotlin에서는 아래와 같은 코드를 짤 수 있습니다.
val age : Int = 19
val str = if (age > 18) {
"어른"
} else {
"아이"
}
println(str)
자바에서 switch라는 메서드는 if 문과 비슷하지만 좀 더 정형화된 조건 판단문입니다.
자바에서의 switch문은 break를 실수로 생략하면 원하지 않는 결과가 나옵니다.
물론 의도하여 break를 제거 할 수도 있지만 그렇지 않은 경우 매번 break를 걸어주고 생략 시 사이드이펙트가 발생 할 수 있습니다.
또 자바의 switch'문'은 미리 변수를 초기화 해놓고 결과값을 넣어줘야하므로 비효율적인 코드가 짜여집니다.
int day = 2;
String result = "";
switch (day) {
case 1:
result = "월요일"; break;
case 2:
result = "화요일"; break;
case 3:
result = "수요일"; break;
case 4:
result = "목요일"; break;
case 5:
result = "금요일"; break;
case 6:
result = "토요일"; break;
case 7:
result = "일요일"; break;
default:
result = "에러"; break;
}
System.out.println(result);
위와 같은 단점을 보완하여 코틀린에서는 when이라는 메서드를 지원해줍니다.
val day = 2
val result = when (day) {
1 -> "월요일"
2 -> "화요일"
3 -> "수요일"
4 -> "목요일"
5 -> "금요일"
6 -> "토요일"
7 -> "일요일"
else -> "에러"
}
println(result)
코틀린의 when 메서드는 else를 생략할 수도 있으며 코틀린이라는 언어를 사용하면서 switch와 when을 선택해서 사용 할 수 있는 것이 큰 매력이라고 봅니다. (break를 의도적으로 사용해야 할 때 switch문 사용)
조건
enum class Color {
RED, GREEN, BLUE
}
fun getColor() = Color.RED
다른 조건으로 하나의 값이 나와야 할 경우
when (getColor()) {
Color.RED, Color.GREEN -> print("color == red or color == green")
else -> print("blue")
}
else문 생략
when (getColor()) {
Color.RED -> println("red")
Color.GREEN -> println("green")
Color.BLUE -> println("blue")
}
코틀린에서 for loop는 기본적으로 자바의 foreach와 유사합니다.
범위 연산자 .. 를 사용해 for loop 돌릴수 있습니다.
코틀린은 0..3인 경우 0 < i < 3가 아닌 0 < i <= 3 처럼 동작합니다.
for (i in 0..3) {
println(i)
}
// 0
// 1
// 2
// 3
만약 0 < i < 3처럼 동작하게 하려면 until을 사용합니다.
until
for (i in 0 until 3) {
println(i)
}
// 0
// 1
// 2
값을 1씩 증가하는게 아닌 증가 폭을 설정하고 싶으면 step을 사용합니다.
step
for (i in 0..6 step 2) {
println(i)
}
// 0
// 2
// 4
// 6
값을 감소시키면서 반복시키는 건 downTo를 사용합니다.
downTo
for (i in 3 downTo 1) {
println(i)
}
// 3
// 2
// 1
받은 배열을 반복문을 통해서 사용하고 싶을 경우
val numbers = arrayOf(1, 2, 3)
for (i in numbers) {
println(i)
}
// 1
// 2
// 3
출처 : fastcampus