접근이란?
- 객체를 이용하여 변수나 메소드를 호출할 수 있는지의 여부
public
private
internal : 같은 모듈 내부
protected : private + 자식
왜 필요할까?
무분별한 접근 통제 가능
클래스들간에 접근하면 안되는 상황을 구분해서 향후 유지보수에 용이
프로젝트 : 최상단 개념이고 <모듈, 패키지, 클래스>를 포함
모듈 : 프로젝트 아래의 개념이고 <패키지, 클래스>를 포함
패키지 : 모듈 아래의 개념이고 <클래스>를 포함
- 프로그램을 실행하기 전에 알 수 있는
컴파일 에러
를오류
라고 함- 프로그램을 실행하는 도중에 발생하는
런타임 에러
인예외
가 발생할 수 있음- 실행 도중 예외가 발생하면 프로그램이 비정상적으로 종료됨
Kotlin의 예외처리 방법
에는 2종류가 있다
// try-catch의 구조
fun method1() {
try {
예외가 발생할 가능성이 존재하는 코드
} catch(예외종류) {
예외가 발생했을때 처리할 코드
}
}
// NPE가 발생하지 않을 때까지 반복하는 구조 (올바른 값을 입력할 때까지)
while(true) {
try {
var num1 = readLine()!!.toInt()
println("내가 입력한 숫자는 ${num1}입니다")
break
} catch(e:java.lang.NumberFormatException) {
println("숫자를 입력하세요")
} finally {
println("키보드와의 연결은 정상적입니다")
}
}
// throw의 구조
fun method1() {
try {
예외가 발생할 가능성이 존재하는 코드
} catch(예외종류) {
예외가 발생했을때 처리할 코드
}
}
while(true) {
try {
var num1 = readLine()!!.toInt()
println("내가 입력한 숫자는 ${num1}입니다")
break
} catch(e:java.lang.NumberFormatException) {
println("숫자를 입력하세요")
} finally {
println("키보드와의 연결은 정상적입니다") // 무조건 실행되는 코드 블럭
}
}
- lateinit or lazy
- 클래스를 설계할 때 초기의 값을 정의하기 난처할 때
- 저사양으로 제한되어있는 환경에서는 메모리를 더욱 효율적으로 사용할 수 있음
변수
의 지연 초기화
lateinit을 사용
isInitialized를 활용해서 값이 초기화되었는지 확인 가능 (true/false)
사용할 때는 값이 아니라 참조형태로 사용해야하기 때문에 this:: 또는 ::을 붙임
fun main() {
var s1 = Student()
s1.name = "참새" // name을 초기화
s1.displayInfo()
s1.age = 10
s1.displayInfo()
}
class Student {
lateinit var name:String
var age:Int = 0
fun displayInfo() {
if(this::name.isInitialized) { // name의 초기화를 확인
println("이름은: ${name} 입니다.")
println("나이는: ${age} 입니다.")
} else {
println("name변수를 초기화해주세요.")
}
}
}
상수
의 지연 초기화
lazy를 사용
상수를 사용하는 시점
에 값을 대입하고 초기화가 수행됨
fun main(){
var s1 = Student()
s1.name = "참새"
s1.displayInfo()
s1.age = 10
s1.displayInfo()
}
class Student {
lateinit var name:String
var age:Int = 0
val address: String by lazy {
println("address 초기화") // 한 번만 실행
"seoul" // address = "seoul"
}
fun displayInfo() {
println("이름은: ${name} 입니다.")
println("나이는: ${age} 입니다.")
println("주소는: ${address} 입니다.")
}
}
- Null예외는 프로그램의 가용성을 저하시키는 치명적인 오류
- Kotlin은 Null예외로부터 안전한 설계를 위해 자료형에 Null 여부를 명시 가능
?, !!, ?., ?:
키워드를 사용- 하지만 강제로 null이 아니라고 하는 !!는 최대한 사용을 지양
?
: null 저장 가능
!!
: null이 아님을 보장
?. (safe-calls)
: null인지 확인하고 아닐 때만 참조, null일 경우 뒤의 메소드를 실행하지 않음
?: (앨비스 연산자)
: null이 아닐 경우 왼쪽, null일 경우 오른쪽 문자열을 출력
var arr = arrayof()
배열을 쓰는 이유 : 반복적으로
변수에 접근하기 위해
Array.toString(변수명)
: 변수에 저장된 배열을 모두 출력
// withIndex() : 두 개의 어떤 값을 묶어서 리턴해줌
for((idx, kors) in kors.withIndex()) {
println("${idx}번째 국어 점수는 ${kor}입니다")
}
}
리스트, 맵, 셋
- 배열과 달리
동적인 크기
- 코틀린에서 컬렉션은 기본적으로
Immutable
로 설계됨
var list = listOf(...)
/ var list = mutableListOf(...)
var arrList = ArrayList<자료형>(...)
: 배열 형태인 리스트
var map = mapOf("key" to value, ...)
/ var map = mutableMapOf("key" to value, ...)
코틀린에서는 for문
으로 맵을 탐색하는 게 쉬움
for((k, v) in map) {
print("${k}의 값은 ${s}입니다")
}
var set = setOf(...)
순서가 없고
중복이 없는
집합 자료형
다른 컬렉션들은 요소를 찾는데에 집중하지만, Set은 요소가 존재하는지에 집중함
// 명령어
set.add()
set.remove()
set.size
set.contains(변수)
union() : 합집합
intersect() : 교집합
subtract() : 차집합
자바 8과 동일하게 코틀린도 람다식
을 지원
// 기본 구조
{매개변수1, 매개변수2... ->
코드
}
// 세 개의 숫자와 평균을 리턴해주는 함수를 람다식으로 정의
fun add (num1:Int, num2: Int, num3: Int) = (num1+num2+num3) / 3
// 메소드를 선언하지 않고 로직을 저장할 수 있음
var add = {num1:Int, num2: Int, num3: Int -> (num1+num2+num3) / 3}
메모리 전역에서 유일한 객체
임을 보장할 수 있음
보통 객체는 자원이 가능한 만큼 생성할 수 있음
각각의 객체는 상이한 위치정보를 가지고 있어서 저장하는 값도 객체마다 고유함
싱글턴을 활용하면 해당 객체는 메모리 전역에서 유일함을 보장하고 위치정보가 고정이에요
프로그램이 실행되는 시점에 메모리에 바로 로드해서 위치를 잡음
코틀린은 companion, object
키워드로 싱글턴을 구현할 수 있음
싱글턴을 활용하는 이유?
- 싱글턴 객체는 전역적으로 활용할 수 있어서 다른 클래스들에서 쉽게 접근할 수 있음
(이미 메모리에 올라가 있기 때문에 인스터스 불필요)- 전역에서 공통적으로 사용하는 정보라면 메모리를 더욱 효율적으로 활용 가능
- 객체 자원간의 충돌을 방지할 수 있음