반응형
지속적으로 업데이트 예정입니다. 틀린 부분 정정해주시는 댓글은 환영입니다.
[ 타입 ]
1. Entry Point
Java | Kotlin | |
Entry Point | public static void main(String[] args) { … } | fun main(args: Array<String>) { ... } |
2. 타입
Java | Kotlin | |
정수형 | byte (1바이트, -128 ~ 127) short (2바이트, -32,768 ~ 32,767) int (4바이트, -2,147,483,648 ~ 2,147,483,647) long (8바이트, -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807) |
Byte Short Int Long 범위는 Java와 같음 |
실수형 | float (4바이트, (3.4 X 10^-38) ~ (3.4 X 10^38)) double (8바이트, (1.7 X 10^-308) ~ (1.7 X 10^308)) 부동소수점은 IEEE-754를 따름 float은 소수점 아래 7자리까지 표현 |
Float (4바이트, (+/-) 1.4 x 10^-45 ~ (+/-) 3.4028235 x 10^38) Double (8바이트, (+/-) 4.9 x10^-324 ~ (+/-) 1.7976931348623157 x 10^308) 부동소수점은 IEEE-754를 따름 float은 소수점 아래 7자리까지 표현 |
문자형 | char (작은 따옴표, 2바이트, ASCII나 유니코드 가능) String (큰 따옴표, Reference Type) |
Char String ($템플릿, """템플릿 지원) |
그 외 | boolean (1바이트) void, Void Object |
Boolean (1바이트) Unit Any |
Unsigned | △, java 8 부터 Integer.parseUnsignedInt -> Integer.toUnsignedString 으로 문자열 형태의 값을 얻을 수 있음 | ○, 접미사 U로 표현 가능 |
Wrapper Class Auto Boxing |
auto boxing | auto boxing |
접미사 | float(F), long(L) 가독성을 위해 대문자로 표기하는 것을 권장 정수 자료형의 범위 밖인 경우, 표기하지 않으면 컴파일 에러 ex) long a = 3100100100; -> Compile Error 실수형은 항상 표기 |
Float(F), Long(L) 가독성을 위해 대문자로 표기하는 것을 권장 항상 표기 |
언더스코어 | △, java 7 부터 지원 | ○ (ex. val a = 1_000_000) |
초기값 할당 | 자동 ex) int a; // 0 ex) char b; // '\u0000' ex) boolean c; // false |
수동 초기화 하지않은 변수 사용 시 컴파일 에러 Compile Error : Variable 'a' must be initialized |
3. 변수 생성 규칙
Java | Kotlin | |
기본 규칙 | 라인 끝 세미콜론 O 여러 라인을 한 줄로 작성할 경우 O 네이밍은 Camel case 네이밍 시작 소문자, 명사형 네이밍 시작 특수문자 사용 불가 네이밍은 클린코드(용도가 명확한 표현) 지향 |
라인 끝 세미콜론 X 여러 라인을 한 줄로 작성할 경우 O 네이밍은 Camel case 네이밍 시작 소문자, 명사형 네이밍 시작 _(언더 바) 사용 가능, object, top-level을 제외한 클래스 내에 private 변수 생성 시에만 권장 네이밍은 클린코드(용도가 명확한 표현) 지향 |
일반 변수 | {타입} {이름} = {값}; | {가변성} {이름}[: 타입] = {값} |
객체형 변수 | {타입} {이름} = new {생성자호출}; | {가변성} {이름}[: 타입] = {생성자호출} |
접근 제어자 | private을 제외한 접근 제어자 표시 | public을 제외한 접근 제어자 표시 |
상수 | final | const |
전역 | static (키워드 순서는 static -> final 권장) 네이밍은 대문자, 단어 사이 언더스코어 |
top-level, object class, companion object 네이밍은 대문자, 단어 사이 언더스코어 |
top-level | × | ○ |
확장 변수 | × | ○ |
변수 은닉화 | getter, setter 함수 정의 | 대체할 getter 변수 get() =, 필요 시 setter 정의 |
Nullable | @NonNull로 표기하지 않는 이상 항상 nullable | 엘비스 연산자 |
lambda | java.util.function의 함수형 인터페이스를 사용하거나 직접 정의하여 이용 | val some = (Int) -> String = { it.toString() } |
같은 코드 예제 | public class Something { public int number = 0; // public, 가변 멤버 public static final long NUMBER_MIN = -100; static final long NUMBER_MAX = 100; // private, 전역 불변 SomeType type = new SomeType(); // 은닉화 대상 public SomeType getType() { return type; } public void setType(SomeType type) { this.type = type; } } |
const val NUMBER_MIN = -100L // top-level, 전역 불변 class Something { var number = 0 // public, 가변 멤버 private var _type = SomeType() // 은닉화 대상 val type get() = _type fun setType(type: SomeType) { _type = type } companion object { private const valNUMBER_MAX = 100L// private, 전역 불변 } } |
4. 함수 생성 규칙
Java | Kotlin | |
기본 규칙 | 네이밍은 Camel case 네이밍 시작 소문자, 동사형 네이밍 시작 특수문자 사용 불가 네이밍은 클린코드(용도가 명확한 표현) 지향 |
네이밍은 Camel case 네이밍 시작 소문자, 동사형 네이밍 시작 특수문자 사용 불가 네이밍은 클린코드(용도가 명확한 표현) 지향 |
일반 함수 | {반환타입} {이름}(...) { ... } | fun {이름}(...): {반환타입} { ... } |
parameters | {타입} {이름}, {타입} {이름}, ... | {이름}: {타입}, {이름}: {타입}, ... |
default value | ×, 메서드 오버로드 이용 | ○, ex) fun foo(p1: Int = 0, p2: String = "") |
return | return {반환값}; | return {반환값} Single Expression 가능 (= {반환값}) |
접근 제어자 | private을 제외한 접근 제어자 표시 | public을 제외한 접근 제어자 표시 |
전역 | static | top-level, object class, companion object |
top-level | × | ○ |
확장 함수 | × | ○ |
trailing comma | × | △, 1.4.0부터 지원 |
Named Argument | × | ○ |
getter setter | 보일러 플레이트, Lombok으로 코드 최적화 가능 | get(), set(value) 제공 |
lambda | java.util.function의 함수형 인터페이스를 사용하거나 직접 정의하여 파라미터로 전달 | fun getSome(block: (Int) -> String) { // ... } |
같은 코드 예제 | public class Something { // ... public String hello(boolean a) { return type.hello(a); } public static String bye() { return type.bye(); } } |
class Something { // ... fun hello(a: Boolean): String = type.hello(a) } fun Something.bye(): String = type.bye() // top-level, 확장 함수 |
5. 클래스 규칙
Java | Kotlin | |
기본 규칙 | 네이밍은 Camel Case 네이밍 시작 대문자, 명사형 네이밍 시작 특수문자 사용 불가 모든 변수 및 함수는 클래스 하위에만 정의 가능 |
네이밍은 Camel Case 네이밍 시작 대문자, 명사형 네이밍 시작 특수문자 사용 불가 |
생성자 | 기본 : 파라미터가 없는 기본 생성자 자동 정의 파라미터를 갖는 생성자 오버로드 시, 기본 생성자도 작성해야 함 |
기본 생성자 정의 불필요 1종류의 생성자는 클래스 이름 다음에 정의 가능 추가 오버로드 시, constructor 키워드를 이용해 클래스 내부에 정의 |
init block | × | ○ |
클래스 종류 | class abstract class enum |
class abstract class open class data class sealed class enum class |
data class | × | 타입 관리에 효과적인 클래스 hashcode(), equals(), toString(), copy() 메소드를 자동으로 생성해줌 모두 override가 가능함 생성자 arguments는 불변성(val) 변수를 정의할 것을 권장함 |
상속 가능 여부 | extends 키워드 이용 하나의 supertype class만 상속할 수 있음 class, abstract class 모두 상속 가능 abstract 키워드가 있는 메소드는 필수적으로 @Override 변수는 @Override할 수 없음 abstract 메소드 초기 정의 불가 키워드가 없는 변수 및 함수는 재정의 가능, 외부 접근 시 우선순위는 말단 자식이 가장 높음 |
:(콜론) 키워드 이용 하나의 supertype class만 상속할 수 있음 open class, abstract class, sealed class 상속 가능 abstract 키워드가 있는 변수 및 함수는 필수적으로 override abstract 변수 및 함수 초기 정의 불가 open 키워드가 있는 변수 및 함수는 선택적으로 override 및 재정의 가능 open 변수 및 함수 초기 정의 가능 open class는 abstract 키워드 사용 불가 sealed class는 abstract와 본질적으로 유사함, enum class의 성질을 추가로 가짐 그러므로 자식 타입이 여러 개인 경우, sealed class를 쓰는 것이 좋음(when) 대신 컴파일 시간을 좀 더 잡아먹음 |
Singleton | Dagger/Hilt 이용하는 경우 @Singleton 직접 구현 |
Dagger/Hilt 이용하는 경우 @Singleton object class |
같은 코드 예제 | enum SomeType { BAD, SO_SO, GOOD; // 상수 네이밍 룰 } abstract class Everything { String data = "1"; abstract String getData(); // 변수는 abstract로 선언 불가 } class Something extends Everything { String data = "2"; @Override String getData() { return data + " on Something"; // 2 on Anything } } |
enum class SomeType { BAD, SO_SO, GOOD } sealed class Everything { abstract val data: String open fun getData(): String { return data } } data class Something( override val data: String, ): Everything() { override fun getData(): String { return "$data on Something" } } |
[ Type operation ]
1. Type check
Java | Kotlin | |
비교 | instanceof 이용 Java에서는 OOP가 매우 중요함. 디버깅 과정이 아닌 이상 이러한 코드 유형을 작성할 일은 거의 없어야 한다. |
is, !is 이용 when으로도 체크 가능 주로 enum, sealed class와 함께 이용, null이어서 타입 체크가 불가능한 경우에는 false 반환 |
같은 코드 예제 | if (obj instanceof SomeType.GOOD) { Log.d("", "success casting to good"); } else if (obj instanceof SomeType.SO_SO) { Log.e("", "failure casting (so so)"); } else { Log.e("", "failure casting (bad)"); Log.e("", "or (null)"); } 또는 if (!(obj instanceof SomeType.GOOD)) { Log.e("", "failure casting to good"); } |
when (obj) { // obj is nullable data SomeType.BAD -> Log.e("", "failure casting (bad)") SomeType.SO_SO -> Log.e("", "failure casting (so so)") SomeType.GOOD -> Log.d("", "success casting to good") else -> Log.e("", "failure casting (null)") } 또는 if (obj !is SomeType.GOOD) { Log.e("", "failure casting to good") } |
2. Type cast
Java | Kotlin | |
비교 | ({타입}) {이름} 형태로 이용 특정한 데이터의 타입 변경 시나리오에서는 파싱 메소드를 제공 (ex. Integer.parseInt("300")) 객체의 명시적 타입이 캐스팅할 타입보다 상위 일 때 컴파일 경고 객체의 명시적 타입이 캐스팅할 타입과 자손 관계가 아닐 때 컴파일 에러 캐스팅 할 객체가 암시적 타입으로 선언된 경우, 캐스팅 타입보다 상위거나 자손 관계가 아닐 때 ClassCastException 발생 |
as, as? 이용 캐스팅이 불확실한 경우에는 AType as? BType의 형태로 캐스팅해야 함 AType as BType? 형태에서 캐스팅이 실패할 경우 ClassCastException 발생 |
같은 코드 예제 | Parent parent = new Parent(); Child1 first = (Child1) parent; // 컴파일 경고 Child2 second = new Child2(); Child1 first = (Child1) second; // 컴파일 에러 Parent first = new Child1(); Child2 second = (Child2) fisrt; // ClassCastException |
val parent = Parent() val first = parent as Child1 // 컴파일 경고, ClassCastException val second = Child2() val first = second as Child1 // 컴파일 경고, ClassCastException val first: Parent = Child1() val second = first as Child2 // 컴파일 경고, ClassCastException |
[ Collections ]
1. Array
Java | Kotlin | |
비교 | 중괄호로 표현 가능, Premitive Type 초기 크기 지정 가능, Reference Type int a[ ] 와 같은 형태로도 선언이 가능하지만, 가독성을 위한 컨벤션 트렌드는 타입 뒤에 대괄호를 붙이는 형태임 (여러 IDE 사이트의 기본 main 문에는 String[] args의 형태로 작성되어 있기도 함) (해당 컨벤션은 성능 차이도 없음) 기본적으로 추가/삭제 불가, 수정 가능 메모리 재할당이나 ArrayList를 이용해 추가/삭제 구현 가능, 자주 변경되는 데이터라면 ArrayList 이용 |
Array 객체 이용 Premitive Type에 매칭되는 Array 객체 이용 가능 (IntArray, BooleanArray, CharArray 등) 모든 Array는 arrayOf의 형태로 초기 선언 가능 초기 크기 지정 가능, 초기값 람다 연산 가능 추가/수정 가능 Array를 가변 변수(var)로 선언한 후, plus() 혹은 + 연산자 이용하여 추가 가능한 방식 filter를 이용하거나 MutableList로 변환하여 삭제 구현 가능 |
같은 코드 예제 | int[ ] a = { 1, 3, 5, 7, 9 }; int[ ] b = new int[5]; // null 초기화 int[ ] c = new int[5] { 1, 3, 5, 7, 9 }; // 추가 int[] newArr = new int[a.length + 1]; System.arraycopy(a, 0, newArr, 0, a.length); newArr[a.length] = 11; a = newArr; // 1, 3, 5, 7, 9, 11 // 수정 a[3] = 19 // 1, 3, 5, 19, 9, 11 // 삭제 int[] newArr = new int[arr.length - 1]; System.arraycopy(a, 0, newArr, 0, a.length - 1); a = newArr; // 1, 3, 5, 19, 9 |
var a = intArrayOf(1, 3, 5, 7, 9) var b = Array<Int>(5) { null } var c = IntArray(5) { it * 2 + 1 } // it is index // 추가 a += 11 // 1, 3, 5, 7, 9, 11 // 수정 a[3] = 19 // 1, 3, 5, 19, 9, 11 // 삭제 a = a.filter { it != 5 }.toIntArray() // 1, 3, 19, 9, 11 a = a.toMutableList().apply { removeLast() }.toIntArray() // 1, 3, 19, 9 |
2. List
Java | Kotlin | |
비교 | List는 abstract class List를 구현한 여러 Collection을 선언하여 이용 ArrayList, LinkedList 추가/수정/삭제 모두 가능 |
불변성의 경우 List 이용 가변성의 경우 MutableList 이용 listOf(), listOf<>() mutableListOf(), mutableListOf<>() List는 emptyList(), emptyList<>()도 가능 위의 형태로 주로 초기화함 모든 Collection은 확장함수 toList()로 캐스팅 가능 Map을 제외한 모든 Collection은 확장함수 toMutableList()로 캐스팅 가능 |
성능 | 0크기 - EmptyList 1크기 - SingletonList 2크기 이상 - ArrayList MutableList === ArrayList 타입을 잘게 쪼개어 놨다. 내부적으로 메모리 관리의 효율성 때문이 아닐까 싶다. |
|
같은 코드 예제 | List<Integer> arrayList = new ArrayList<>(10); // param '10' is not array length List<Integer> linkedList = new LinkedList<>(arrayList); arrayList.set(3, 19); // IndexOutOfBoundsException arrayList.set(9, 20); // IndexOutOfBoundsException arrayList.add(5); linkedList.add(8); |
val list = List<Int>(5) { it * 2 + 1 } val empty = emptyList<Int>() // length = 0 val mutable: MutableList<Int> = mutableListOf() var mutable2 = mutableListOf<Int>() // Bad, duplicated mutable list.add(19) // Compile error mutable.add(19) // Good val newList = list.toMutableList() newList.add(19) // Good |
3. Set
Java | Kotlin | |
비교 | Set은 abstract class Set을 구현한 여러 Collection을 선언하여 이용 ArraySet, HashSet, TreeSet, LinkedHashSet 등 추가/삭제 가능, 순서가 없기 때문에 수정 불가 |
불변성의 경우 Set 이용 가변성의 경우 MutableSet 이용 setOf(), setOf<>() mutableSetOf(), mutableSetOf<>() Set은 emptySet(), emptySet<>()도 가능 위의 형태로 주로 초기화함 Map을 제외한 모든 Collection은 확장함수 toSet(), toMutableSet()으로 캐스팅 가능 |
성능 | 기본적으로 HashSet의 구조 contains 성능이 O(1) |
|
같은 코드 예제 | Set<Integer> hashSet = new HashSet<>(); hashSet.add(3); hashSet.remove(3); |
val set = mutableSetOf<Int>() set.add(3); set.remove(3); |
4. Map
Java | Kotlin | |
비교 | Map은 abstract class Map을 구현한 여러 Collection을 선언하여 이용 ArrayMap, HashMap, TreeMap, LinkedHashMap 등 추가/수정/삭제 모두 가능 삭제 시 key 하나만 넣거나, key-value를 모두 넣어 boolean 값을 반환받을 수 있음 |
불변성의 경우 Map 이용 가변성의 경우 MutableMap 이용 mapOf(), mapOf<>() mutableMapOf(), mutableMapOf<>() Map은 emptyMap(), emptyMap<>()도 가능 위의 형태로 주로 초기화함 모든 Collection은 확장함수 associateBy()으로 캐스팅 가능 |
성능 | 기본적으로 HashMap의 구조 containsKey 성능이 O(1) |
|
같은 코드 예제 | Map<Integer, Integer> hashMap = new HashMap<>(); hashMap.put(0, 19); hashMap.put(3, 20); int a = hashMap.get(5); // unboxing fail warning, because may return null hashMap.remove(4); // do nothing |
val map = mutableMapOf<Int, Int>() map[0] = 19 map[3] = 20 val a = map[5] // null map.remove(4) // do nothing |
반응형
'내 것 만들기' 카테고리의 다른 글
(백준) "7579번: 앱" 문제를 풀며 리소스 관리 공부하기(?) | pseudo, kotlin (0) | 2024.08.23 |
---|---|
보잘 것 없는 주니어의 Google Gemini API Competition 출전 썰 | 그런데 Android Jetpack Compose를 곁들인.. (0) | 2024.08.13 |