Programming/Kotlin
Java와 Kotlin 비교 : 변수, null 안정성, 엘비스 연산자, 가변/불변 컬렉션
Renechoi
2023. 10. 22. 11:45
변수
public class Exam01 {
public Exam01(){
String name = "홍길동";
String format ="사용자의 이름은 : %s";
String result = String.format(format, name);
System.out.println(result);
int age = 10;
Integer _age = 20;
double d = 10d;
Double _d = 20.0;
float f = 20f;
Float _f = 20f;
long l = 10L;
Long _l = 10L;
}
}
fun main() {
// var -> mutable, val -> final(불변)
// : [타입]
val name: String = "홍길동"
var _name: String = "홍길동"
val n = "홍길동" // <- 타입 추론
// 코틀린은 primitive 타입이 없고 전부 레퍼런스 타입 -> 모든 것을 객체로 관리한다.
var i = 10
var _i: Int = 10
var d: Double = 20.0
println("사용자의 이름은: $name")
}
변수 선언
Java
String name = "홍길동";
Kotlin
val name: String = "홍길동"
- Java에서는
String name = "홍길동";
과 같은 방식으로 변수를 선언한다. - Kotlin에서는
val name: String = "홍길동"
과 같이 선언한다. 여기서val
은 final이라는 것을 의미하며, 이 변수는 불변이다.
자료형
Java
int age = 10;
double d = 10d;
Kotlin
var age: Int = 10
var d: Double = 10.0
- Java에서는 기본형(primitive types)과 참조형(reference types)이 있다.
- Kotlin에서는 모든 것이 객체. 따라서,
int
대신Int
,double
대신Double
을 사용한다.
출력
Java
System.out.println("사용자의 이름은 : " + name);
Kotlin
println("사용자의 이름은: $name")
- Java에서는 문자열 연결을 통해 출력을 한다.
- Kotlin에서는 문자열 템플릿을 사용하여
$변수명
형태로 쉽게 출력할 수 있다.
null 안정성과 엘비스 연산자
이번에는 Java와 Kotlin의 null 안정성과 엘비스 연산자에 대해 알아보자.
public class Exam02 {
private int a;
public Exam02(){
var b = 20; // <- 자바도 타입추론이 가능하다. 대신 자바에는 불변 변수 val은 없음 -> null도 안됨. 반드시 타입이 들어가야함
int c = 30;
Integer d = 20;
Integer e = new Integer(null);
callFunction(a);
callFunction(b);
callFunction(c);
callFunction(d);
callFunction(e); // -> null로 들어오면서 에러 발생
}
public void callFunction(Integer i ){
System.out.println("i = " + i);
var temp = (i == null) ? "null 입니다" : i;
System.out.println("temp = " + temp);
}
}
fun main(){
val a: Int = 0
val b = 10
val c: Int = 20
val d: Int? = null // 엘비스 연산자 - > 의미는 -> null 값이 들어올 수 있다
callFunction(a)
callFunction(b)
callFunction(c)
callFunction(d)
// 자바랑 100% 호환되므로 optional이 가능
Optional.ofNullable(d).ifPresent() ...
}
fun callFunction(i: Int?){ // i라는 값이 null일 수도 있다
println(i) // 별도의 null 포인트를 터지지 않고 그냥 찍는다.
// 코틀린에는 let이라는 함수가 있음. 물음표를 붙이면 i에 대해서 검증을 함
i?.let{
}
// 엘비스 연산자 -> null이 올 수도 있다. -> 이 뒤에 null을 방지할 수 있다. 변수 뒤에다 ?를 붙이면 변수가 null이야?
// ?. << 변수가 null이 아닐 때
// ?: << 변수가 null일 때
i?.let{
println(it)
} ?: run {
println("null 입니다")
}
// 자바에서 비슷하게 한다면
var temp1 = (i == null) ? "null 입니다" : i;
System.out.println("temp = " + temp1);
// ->
val temp2: Serializable = i ?: "null 입니다"
println("temp = $temp2")
// 코틀린에서 강한 부분 -> 굉장히 간단
val temp3 = i?: "null입니다"
println(temp3)
}
fun callFunction2(i: Int? =100){
// default로 매개변수에 지정을 해줄 수 있음 -> null이 넘어오거나 값이 안넘어올 수도 있다
}
Null 안정성
Java
Integer e = new Integer(null);
Kotlin
val d: Int? = null
- Java에서는
Integer
와 같은 객체를null
로 초기화할 수 있다. 하지만 이 경우, 해당 변수를 사용할 때 null 체크를 해야 한다. - Kotlin에서는
Int?
와 같이 타입 뒤에?
를 붙여서 null이 될 수 있는 변수임을 명시적으로 표현한다.
엘비스 연산자
Java
var temp = (i == null) ? "null 입니다" : i;
Kotlin
val temp = i ?: "null 입니다"
- Java에서는 삼항 연산자를 이용해 null 체크를 해야한다.
- Kotlin에서는 엘비스 연산자
?:
를 사용하여 간단하게 null 체크와 값을 할당할 수 있다.
Optional 클래스와 호환성
Kotlin은 Java와 100% 호환되므로, Java의 Optional
클래스를 사용할 수 있습니다.
Optional.ofNullable(d).ifPresent { ... }
기타 Kotlin null 안정 기능
Kotlin에서는 ?.
연산자와 let
함수, run
함수 등을 활용하여 null 체크를 간편하게 할 수 있다.
i?.let {
println(it)
} ?: run {
println("null 입니다")
}
확실히, 엘비스 연산자와 ?.
, let
, run
등을 활용하면 코드가 훨씬 간결하고 안전해진다.
가변, 불변 컬렉션
이번에는 Java와 Kotlin의 컬렉션, 특히 가변과 불변 컬렉션에 대해 비교해보자.
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
class User {
private String name;
private int age;
}
public class Exam03 {
public Exam03() {
var userList = new ArrayList<User>();
userList.add(new User("1", 10));
userList.add(new User("2", 10));
userList.add(new User("3", 10));
var list = Arrays.asList(
new User("4" , 20),
new User("5" , 20),
new User("6" , 20)
);
userList.forEach(System.out::println);
for (int i =0; i< userList.size(); i++){
var dto = userList.get(i);
System.out.println("i = " + i);
}
// 자바에서도 immutable을 제공 -> but 가변 메서드가 사용되기 때문에 -> 에러 발생
var immutable = Collections.unmodifiableCollection(userList);
immutable.add(new User("5", 60));
}
}
fun main() {
// 코틀린에서는 불변과 가변을 중요하게 나눔
// 변수에서처럼 컬렉션에서도 ->
val userList = mutableListOf<User>()
userList.add(User("1", 10))
userList.add(User("2", 10))
userList.add(User("3", 10))
// 불변 -> 반드시 초기화때 넣어주어야 함 -> add라는 메서드가 지원을 안함
// 자바에서는 불변이어도 add가 보이지만
val list = listOf<User>(
User("4", 40)
)
for(element in userList){
println(element)
}
userList.forEach{it->println(it)}
userList.forEach{ println(it)}
// index를 보고 싶은 경우에
userList.forEachIndexed{index, user -> println("$index, $user") }
userList.forEachIndexed(fun (index, user){
println("$index, $user")
})
// for문에다가 넣는 방식
for ((index, element) in userList.withIndex()){
println("$index, $element")
}
}
class User(
var name: String,
var age: Int
)
가변 컬렉션
Java
var userList = new ArrayList<User>();
userList.add(new User("1", 10));
Kotlin
val userList = mutableListOf<User>()
userList.add(User("1", 10))
- Java와 Kotlin 모두 가변 컬렉션을 제공한다.
- Java에서는
ArrayList
를 주로 사용하고, Kotlin에서는mutableListOf
를 사용한다.
불변 컬렉션
Java
var immutable = Collections.unmodifiableCollection(userList);
immutable.add(new User("5", 60)); // 에러 발생
Kotlin
val list = listOf<User>(
User("4", 40)
)
- Java에서 불변 컬렉션을 만들기 위해서는
Collections.unmodifiableCollection
메서드를 사용한다. 하지만 이 컬렉션에add
메서드를 호출하면 런타임에서 에러가 발생한다. - Kotlin에서는
listOf
를 이용해서 불변 컬렉션을 생성할 수 있다. 불변 컬렉션에서add
메서드가 제공되지 않으므로, 컴파일 시점에서 에러를 확인할 수 있다.
순회 방법
Java
for (int i = 0; i < userList.size(); i++) {
var dto = userList.get(i);
System.out.println("i = " + i);
}
Kotlin
for ((index, element) in userList.withIndex()) {
println("$index, $element")
}
- Java에서는 전통적인 for문이나 forEach 메서드를 사용하여 컬렉션을 순회한다.
- Kotlin에서는
forEach
,forEachIndexed
,withIndex
등 다양한 방법으로 컬렉션을 순회할 수 있다. -> 인터페이스가 더 많다.
결론
Kotlin에서는 불변성을 중요하게 생각하여, 컬렉션에서도 불변과 가변을 명확히 구분한다. 또한, 컬렉션을 순회하는 방법도 다양하고 직관적이다. 이로 인해 코드가 간결하고 안전하며, 유지보수하기 쉽다.
reference :
- fastcampus 시그니처 백엔드 path 초격차 패키지 course 5
- https://kotlinlang.org/spec/introduction.html#reference
반응형