코틀린의 핵심 개념을 자바와 비교하며 코드와 함께 정리합니다.
.kt이다. public이다. System.out.println() 대신 println()만 작성해도 된다. fun이라는 키워드를 사용한다. fun이라는 단어는 '재밌는'이라는 뜻도 갖고 있어서 가끔 fun fun(재밌는 함수)라는 외국 드립이 보일 때도 있다. '타입 변수명'을 사용했지만, 코틀린에서는 TypeScript와 유사하게 '변수명: 타입'을 사용한다. 코틀린에서는 null을 허용하려면 ?를 붙여야 합니다.
String name = null; // 가능
var name: String? = null // `?`를 붙여야 null 허용
name?.length // null 안전 처리
코틀린에서는 null을 직접 다루지 않고 안전하게 처리하는 방법을 제공합니다.
코틀린은 타입 추론을 지원합니다.
String text = "Hello";
int number = 42;
val text = "Hello" // 자동으로 String으로 인식
val number = 42 // 자동으로 Int로 인식
코틀린에서는 == 연산자가 값 비교, === 연산자가 참조 비교입니다.
String a = new String("hello");
String b = new String("hello");
System.out.println(a == b); // false (참조 비교)
System.out.println(a.equals(b)); // true (값 비교)
val a = "hello"
val b = "hello"
println(a == b) // true (값 비교)
println(a === b) // false (참조 비교)
코틀린에서는 if와 when을 활용해 조건을 평가합니다.
int score = 85;
String grade;
if (score >= 90) {
grade = "A";
} else {
grade = "B";
}
val score = 85
val grade = if (score >= 90) "A" else "B"
println(grade)
또한 when을 사용하면 더 깔끔한 코드가 가능합니다.
val grade = when (score) {
in 90..100 -> "A"
in 80..89 -> "B"
else -> "C"
}
코틀린에서는 for와 while을 지원하며 for-in 문법을 사용할 수 있습니다.
for (int i = 0; i < 5; i++) {
System.out.println(i);
}
for (i in 0..4) {
println(i)
}
..을 사용하면 범위 지정이 가능합니다.
코틀린에서는 try-catch를 사용해 예외를 처리합니다.
try {
int result = 10 / 0;
} catch (ArithmeticException e) {
System.out.println("예외 발생: " + e.getMessage());
}
try {
val result = 10 / 0
} catch (e: ArithmeticException) {
println("예외 발생: ${e.message}")
}
코틀린은 간결한 함수 선언이 가능합니다.
public class Main {
public static void main(String[] args) {
int result = add(5, 10);
System.out.println("Result: " + result);
}
public static int add(int a, int b) {
return a + b;
}
}
fun main() {
val result = add(5, 10)
println("Result: $result")
}
fun add(a: Int, b: Int): Int {
return a + b
}
코틀린에서는 class를 사용해 클래스를 정의할 수 있습니다.
public class Main {
public static void main(String[] args) {
Person person = new Person(23, "dsg");
person.greeting();
}
}
class Person {
private int age;
private String name;
public Person(int age, String name) {
this.age = age;
this.name = name;
}
public void greeting() {
System.out.println("Hello age " + age + ", " + name + "!");
}
}
fun main() {
var person = Person(23,"dsg")
person.greeting()
}
class Person(var age: Int, var name: String) {
fun greeting() {
print("Hello age $age, $name!")
}
}
코틀린은 간결한 클래스 선언이 가능합니다.
코틀린에서는 open 키워드를 사용해 상속을 허용합니다.
class Animal {
void speak() {
System.out.println("Animal speaks");
}
}
class Dog extends Animal {
void speak() {
System.out.println("Dog barks");
}
}
open class Animal {
open fun speak() = println("Animal speaks")
}
class Dog : Animal() {
override fun speak() = println("Dog barks")
}
코틀린에서는 public, private, protected, internal을 사용하여 접근 제어를 할 수 있습니다.
public class Person {
private String name;
public Person(String name) {
this.name = name;
}
private void greet() {
System.out.println("Hello, " + name);
}
}
class Person(private val name: String) {
private fun greet() = println("Hello, $name")
}
코틀린에서는 기본적으로 public이므로 명시하지 않아도 됩니다.
object 키워드를 다루는 방법코틀린에서는 object를 사용하여 싱글턴 객체를 만들 수 있습니다.
class Singleton {
private static Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
object Singleton {
fun greet() = println("Hello from Singleton")
}
코틀린에서는 object 키워드만 사용하면 싱글턴을 간편하게 만들 수 있습니다.
코틀린은 inner class를 사용하여 중첩 클래스를 정의할 수 있습니다.
class Outer {
class Inner {
void greet() {
System.out.println("Hello from Inner Class");
}
}
}
class Outer {
inner class Inner {
fun greet() = println("Hello from Inner Class")
}
}
코틀린에서 inner를 명시해야 외부 클래스의 멤버에 접근할 수 있습니다.
코틀린에서는 data class, sealed class를 사용하여 다양한 클래스를 정의할 수 있습니다.
class User {
String name;
int age;
User(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "User{name='" + name + "', age=" + age + "}";
}
}
data class User(val name: String, val age: Int)
data class를 사용하면 toString, equals, hashCode가 자동 생성됩니다.
코틀린에서는 배열과 컬렉션을 편리하게 다룰 수 있습니다.
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
for (String name : names) {
System.out.println(name);
}
Map<String, Integer> testMap = new HashMap<>();
testMap.put("Alice", 25);
testMap.put("Dsg", 33);
testMap.put("kmb", 33);
System.out.println(testMap);
fun main() {
var tests = listOf("dsg","rf","rt")
// 1. 전통적인 방법
for (test in tests) {
println("test: $test")
}
// 2. 코틀린 -> 람다 사용법, it
tests.forEach{it -> println("test2: $it")}
// 3. it 축약
tests.forEach{println("test3: $it")}
// map
var testMap = mapOf("Alice" to 25, "dsg" to 33, "kmb" to 34)
println(testMap)
}
코틀린에서는 List 컬렉션을 listOf를 사용하면 간결하게 리스트를 만들 수 있습니다.
코틀린에서 Map 컬렉션을 mapOf를 사용하면 간결하게 리스트를 만들 수 있습니다. MutableMapOf() 를 사용하면 가변적으로 만들 수 있습니다.
코틀린에서는 확장 함수를 활용할 수 있습니다.
class Utils {
static String greet(String name) {
return "Hello, " + name;
}
}
fun String.greet() = "Hello, $this"
println("Alice".greet())
코틀린에서는 기존 클래스에 새로운 메서드를 추가할 수 있습니다.
코틀린에서는 람다 표현식을 간결하게 사용할 수 있습니다.
Function<Integer, Integer> square = x -> x * x;
System.out.println(square.apply(4));
val square: (Int) -> Int = { x -> x * x }
println(square(4))
코틀린에서는 map, filter, reduce 등을 활용하여 컬렉션을 함수형으로 처리할 수 있습니다.
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> squaredNumbers = numbers.stream()
.map(n -> n * n)
.collect(Collectors.toList());
val numbers = listOf(1, 2, 3, 4, 5)
val squaredNumbers = numbers.map { it * it }
println(squaredNumbers)
코틀린에서는 map을 사용하여 간결하게 변환할 수 있습니다.
코틀린에는 다양한 기능이 있습니다.
코틀린을 활용하면 더욱 효율적인 개발이 가능합니다.
코틀린에서는 let, run, apply, also, with을 사용하여 스코프를 효과적으로 관리할 수 있습니다.
val user = User("Alice", 25).apply {
println("User 생성됨: $name, 나이: $age")
}
apply를 활용하면 객체의 초기 설정을 간편하게 할 수 있습니다.