본문 바로가기
728x90

전체 글252

아이템 45 - 불필요한 객체 생성을 피하라 객체 생성은 언제나 비용이 들어갑니다.상황에 따라 굉장히 큰 비용이 들어갈 수도 있습니다.따라서 불필요한 객체 생성을 피하는 것이 최적화의 관점에서 좋습니다JVM 에서는 하나의 가상 머신에서 동일한 문자열을 처리하는 코드가 여러 개 있다면, 기존의 문자열을 재사용합니다.문자열 상수의 재사용 (String Pool)JVM에서 문자열은 불변(immutable) 객체입니다. 즉, 한 번 생성된 문자열은 변경할 수 없습니다. JVM은 이러한 문자열의 특성을 활용하여 String Pool이라는 메모리 공간을 사용합니다.String Pool이란?String Pool은 JVM이 관리하는 특별한 메모리 영역으로, 동일한 문자열 리터럴이 여러 번 생성되는 것을 방지하고 메모리를 절약하기 위해 사용됩니다.만약 코드에서 동.. 2024. 8. 10.
아이템 44 - 멤버 확장 함수의 사용을 피하라 어떤 클래스에 대한 확장 함수를 정의할 때 이를 멤버로 추가하는 것은 좋지 않습니다.확장 함수는 첫 번째 아규먼트로 리시버를 받는 단순한 일반 함수로 컴파일됩니다. 왜 멤버 확장 함수를 피해야 하는가?혼란스러운 함수 스코프:멤버 확장 함수는 해당 함수가 어디서 사용 가능한지, 또는 어떤 클래스에 속하는지 혼동을 일으킬 수 있습니다. 예를 들어, 함수가 멤버 함수인지 확장 함수인지 명확하지 않으며, 사용 범위가 제한되기 때문에 코드의 가독성을 해치게 됩니다.예상치 못한 동작:멤버 확장 함수는 일반적인 확장 함수와 다르게 동작할 수 있습니다. 특정 클래스 내부에서만 접근 가능한 확장 함수는 그 클래스의 외부에서는 전혀 보이지 않으며, 이는 코드의 일관성을 깨트리고 예상치 못한 동작을 초래할 수 있습니다.코드.. 2024. 8. 10.
아이템 43 - API 의 필수적이지 않는 부분을 확장 함수로 추출하라 클래스의 메서드를 정의할 때는 메서드를 멤버로 정의할 것인지 아니면 확장 함수로 정의할 것인지 결정해야 합니다. 멤버 함수로 정의한 경우class Circle(val radius: Double) { // 멤버 함수로 정의된 메서드 fun area(): Double { return Math.PI * radius * radius }}fun main() { val circle = Circle(5.0) println("Area: ${circle.area()}") // 멤버 함수 호출} 확장 함수로 정의한 경우class Circle(val radius: Double)// 확장 함수로 정의된 메서드fun Circle.area(): Double { return Math... 2024. 8. 10.
아이템 42 - compareTo 의 규약을 지켜라 compareTo 메서드는 Any 클래스에 있는 메서드가 아닙니다.이는 수학적인 부등식으로 변환되는 연산자 입니다.  compareTo는 객체의 자연 순서를 정의하는 메서드로, 코틀린에서는 Comparable 인터페이스를 구현할 때 반드시 준수해야 할 중요한 규약을 가진다. 이 규약을 올바르게 준수하지 않으면, 정렬이나 이진 탐색 같은 알고리즘에서 예기치 못한 결과가 발생할 수 있다. compareTo 규약반사성 (Reflexive): a.compareTo(a) == 0은 항상 true여야 한다.대칭성 (Symmetric): a.compareTo(b) == 0이면 b.compareTo(a) == 0도 성립해야 한다.추이성 (Transitive): a.compareTo(b) > 0이고 b.compareTo.. 2024. 8. 10.
아이템 41 - hashCode 의 규약을 지켜라 hashCode 함수는 해시 테이블을 구축할 때 사용된다.임의의 길이를 가진 데이터를 고정된 길이의 데이터로 변환(매핑)하는 것이러한 과정을 해싱 한다고 하며, 해시함수에 얻어진 값을 보통 다이제스트(digest)라고 한다.키 값의 무한성과 해시 함수 출력 값의 유한성 때문에 충돌이 일어날 수 있다. 가변성과 관련된 문제:요소가 추가될 때만 해시 코드를 계산합니다.요소가 변경되어도 해시 코드는 계산되지 않으며, 버킷 재배치도 이루어지지 않습니다.그래서 기본적인 LinkedHashSet 와 LinkedHashMap 의 키 는 한번 추가한 요소를 변경할 수 없습니다.=> 해시 기반 컬렉션에서는 키로 사용되는 객체가 불변이어야 한다. 키 객체가 변경 가능한 속성을 가진다면, 객체를 해시 테이블에 추가한 후에 .. 2024. 8. 1.
아이템 40 - equals 의 규약을 지켜라 Any 에는 다음과 같이 잘 설정된 규약들을 가진 메서드들이 있다- equals- hashCode- toString 동등성코틀린에는 두 가지 종류의 동등성이 있습니다.구조적 동등성: equals 메서드와 이를 기반으로 만들어진 == 연산자(!= 포함)로 확인하는 동등성a 가 nullable 이 아니라면 a == b 는 a.equals(b)로 변환되고 a 가 nullalbe 이라면 a?.equals(b) ?: (b === null) 로 변환레퍼런스적 동등성: ===, !==  연산자로 확인하는 동등성두 피연산자가 같은 객체를 가리키면, true 를 리턴합니다.data class Person(val name: String, val age: Int) { override fun equals(other: A.. 2024. 8. 1.
아이템39 - 태그 클래스보다는 클래스 계층을 사용하라 태그 클래스(tagged class): 상수 모드를 태그라고 부르고, 태그를 포함한 클래스-> 객체 타입을 나타내기 위해 필드를 사용하고, 해당 필드에 따라 동작이 달라지는 클래스를 의미.  태그 클래스의 문제점:복잡성 증가: 하나의 클래스에 여러 유형의 객체를 처리하기 위한 코드가 포함되어 복잡성이 증가합니다.유지보수 어려움: 새로운 유형이 추가될 때마다 기존 코드를 수정해야 하므로 유지보수가 어렵습니다.가독성 저하: 태그를 기반으로 분기하는 코드가 많아지면 코드의 가독성이 떨어집니다.클래스 계층의 장점:명확한 구분: 각 클래스가 자신의 책임을 가지므로 코드가 명확해집니다.확장성: 새로운 유형을 쉽게 추가할 수 있습니다.유지보수 용이: 각 클래스가 독립적이기 때문에 수정이 용이합니다. 태그 클래스 사용.. 2024. 8. 1.
아이템 38 - 연산 또는 액션을 전달할 때는 인터페이스 대신 함수 타입을 사용하라 SAM: Single-Abstract Method인터페이스의 단점:불필요한 복잡성: 인터페이스를 정의하고 이를 구현하는 클래스가 필요합니다.코드 가독성 저하: 인터페이스와 이를 구현하는 클래스를 찾기 위해 코드 베이스를 여기저기 탐색해야 합니다.함수 타입의 장점:간결함: 함수 타입을 사용하면 코드가 더 간결하고 직관적입니다.가독성 향상: 람다 표현식을 사용하여 코드를 읽기 쉽고 유지보수하기 쉽게 만들 수 있습니다.유연성: 함수 타입을 사용하면 필요에 따라 더 유연하게 코드를 작성할 수 있습니다.예시:인터페이스를 사용한 코드:interface ButtonClickListener { fun onClick()}class MyButton : ButtonClickListener { override fu.. 2024. 8. 1.
아이템 37 - 데이터 집합 표현에 data 한정자를 사용하라 Kotlin에서는 데이터 집합을 표현할 때 data 클래스를 사용하면 여러 가지 편리한 기능을 자동으로 제공받을 수 있습니다. data 클래스를 사용하면 코드가 간결해지고, 데이터 객체의 비교, 복사, 문자열 표현 등을 쉽게 처리할 수 있습니다.equals: 객체의 내용을 비교합니다.hashCode: 객체의 해시 코드를 생성합니다.toString: 객체의 문자열 표현을 제공합니다.copy: 객체를 복사할 수 있습니다.(얕은 복사)componentN: 객체의 각 속성에 접근할 수 있습니다.// 얕은복사data class Address(var street: String, var city: String)data class Person(var name: String, var address: Address)fun.. 2024. 7. 14.
728x90