접근 제한자
접근 제한자란? : 변수나 메소드의 접근을 제한
접근이란? : 객체를 이용해서 변수나 메소드를 호출할 수 있는지의 여부
프로젝트: 최상단 개념이고 모듈, 패키지, 클래스를 포함
모듈 : 프로젝트 아래의 개념이고 패키지, 클래스를 포함
패키지 : 모듈 아래의 개념이고 클래스를 포함
public: 명시하지 않으면 기본적으로 public(어디서나 접근 가능)
private: 동일한 클래스 내부에서만 접근 가능
internal: 같은 모듈 내부에서만 접근 가능
protected: 기본적으로 private이지만 상속을 받은 경우에 타 모듈에서 접근 가능
예외 처리의 활용
* 예외 처리의 활용 : 프로그램 실행도중에 발생하는 예외를 적절하게 처리하기 위함
- 프로그램을 실행하기 전에 알 수 있는 컴파일 에러를 오류라 함
- 프로그램을 실행하는 도중에 발생하는 런타임 에러를 예외라 함
- 실행 도중 예외가 발생하면 프로그램이 비정상적으로 종료
예외 처리 사용 이유? : 안정성을 높이기 위해
* try-catch 구조 및 예제
fun method1() {
try {
예외가 발생할 가능성이 존재하는 코드
} catch(예외종류) {
예외가 발생했을때 처리할 코드
}
}
//숫자를 입력해야 하는데 문자를 입력했을 경우 예시(try-catch)
while(true) {
try {
var num1 = readLine()!!.toInt()
println("내가 입력한 숫자는 ${num1}입니다")
break
} catch(e:java.lang.NumberFormatException) {
println("숫자를 입력하세요")
}
}
//예시2(try-catch-finally)
while(true) {
try {
var num1 = readLine()!!.toInt()
println("내가 입력한 숫자는 ${num1}입니다")
break
} catch(e:java.lang.NumberFormatException) {
println("숫자를 입력하세요")
} finally {
println("키보드와의 연결은 정상적입니다")
}
}
-> finally는 try-catch와 상관없이 항상 실행되는 구문
-> catch 안에 들어가는 예외 종류는 오류 명칭을 작성
* throw 구조
fun method1(num1:Int) {
if(num1 > 10) {
throw 예외종류
}
}
* 결론
-> 예외가 발생했을 때 안정적으로 로그 또는 기록을 남기려면 try-catch
-> 그냥 오류를 넘기기만 할 경우는 throw
지연 초기화
* 지연 초기화란?
- 클래스를 설계할 때 안정성을 위해 반드시 변수의 값을 초기화할 것을 권장
- 클래스를 설계할 때 초기의 값을 정의하기 난처해서 나중에 대입하기 위한 문법
- 저사양일 경우 더 효율적으로 사용하기 위해서 쓰임(초기에 값이 전부 입력되어 있는 경우보다 필요할 때 초기화하는 경우가 더 효율적이기 때문)
- 변수는 lateinit으로 상수는 lazy로 지연초기화 함
* 변수의 지연초기화
- 변수를 사용하기 전에 초기화되었는지 확인해야 안정성을 높일 수 있음 -> isInitialized를 활용해서 확인 (true/false)
- isInitialized 사용할 때는 값이 아니라 참조형태로 사용해야하기 때문에 this:: 또는 ::를 붙임
* 변수의 지연 초기화 예제(lateinit + isInitialized 활용)
fun main(){
var s1 = Student()
s1.name = "참새"
s1.displayInfo()
s1.age = 10
s1.displayInfo()
}
class Student {
lateinit var name:String
var age:Int = 0
fun displayInfo() {
if(this::name.isInitialized) {
println("이름은: ${name} 입니다.")
println("나이는: ${age} 입니다.")
} else {
println("name변수를 초기화해주세요.")
}
}
}
* 출력 결과
이름은: 참새 입니다.
나이는: 0 입니다.
이름은: 참새 입니다.
나이는: 10 입니다.
-> lateinit은 변수 선언 맨 앞에 작성
-> .isInitialized(변수를 사용하기 전에 초기화되었는지 확인)를 활용하지 않고 작성할 수 있으나 안정성 및 성능이 저하됨
-> 성능 저하 이유 : 초기화 여부를 확인하지 않으면 예외가 발생, 이로 인해 try - catch 문구도 사용해야 함
-> main 메소드에 변수 name에 대한 선언이 없을 경우 else문 내용이 출력된다.
* 상수의 지연 초기화(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" //초기화 값
}
fun displayInfo() {
println("이름은: ${name} 입니다.")
println("나이는: ${age} 입니다.")
println("주소는: ${address} 입니다.")
}
}
* 출력 결과
이름은: 참새 입니다.
나이는: 0 입니다.
address 초기화
주소는: seoul 입니다.
이름은: 참새 입니다.
나이는: 10 입니다.
주소는: seoul 입니다.
-> lazy는 by lazy 형식으로 작성
-> 중괄호 안에 첫 줄에는 초기화되었을 때 출력할 코드, 다음 줄에는 초기화 값 입력
널 세이프티
* 널 세이프티
- Null 예외는 프로그램의 가용성을 저하시키는 치명적인 오류임
- 코틀린은 이 Null 예외로부터 안전한 설계를 위해 자료형에 Null 여부를 명시할 수 있음
* 널 세이프티 방법
-?,!!,?.,?: 를 이용하여 널 예외로부터 벗어나려고 함
- 강제로 null이 아니라고 하는!! 는 최대한 사용 지양
? : null도 저장할 수 있음
!!(널 단언 연산자) : null 아님을 단언
* ? 예제
fun main(){
var s = Student()
s.name = "참새"
s.address = "서울"
s.displayInfo()
}
class Student {
lateinit var name:String
var address:String? = null
fun displayInfo() {
println("이름은: ${name} 입니다")
println("주소는: ${address} 입니다")
}
}
* 출력 결과
이름은: 참새 입니다
주소는: 서울 입니다
-> 만약 s.address에 서울을 넣지 않을 경우 "주소는: null"입니다 가 출력 됨
* !! 예제
fun main(){
// var data = readLine()!!.toInt()
var inputData = readLine()!!
var data = inputData.toInt()
println("Null아닌 값: ${data}")
}
-> !!(널 단언 연산자)가 있어서 위에 주석처리한 readLine()!!.toInt()도 사용가능
?.(안전 호출 연산자, safe-calls)
- ?. 키워드로 Null인지 확인하고 Null이 아닐 때만 참조하는 메소드를 실행하도록 작성할 수 있음
* ?. 예제
fun main(){
var s = Student()
s.name = "참새"
s.displayAddressLength()
s.address = "서울"
s.displayInfo()
}
class Student {
lateinit var name:String
var address:String? = null
fun displayInfo() {
println("이름은: ${name} 입니다")
println("주소는: ${address} 입니다")
}
fun displayAddressLength() {
println("주소의 길이는: ${address?.length} 입니다")
}
}
* 출력 결과
주소의 길이는: null 입니다
이름은: 참새 입니다
주소는: 서울 입니다
* s.displayAddressLength()와 s.displayInfo()의 위치를 바꾼 후 출력 결과
이름은: 참새 입니다
주소는: null 입니다
주소의 길이는: 2 입니다
-> 해당 예제는 주소를 저장하는 address는 초기값이 null이기 때문에 null 위협에 놓여있음
-> 그래서 Null이 아님을 보장해야 하는데 강제로 !!를 사용하는 것이 좋지 않은 상황이라 ?.(안전 호출 연산자)를 사용함
-> null이 아닐 때만 주소의 길이를 호출하여 출력합니다. 만약 null일 경우 그냥 null을 출력
* ?:(엘비스 연산자)
- 키워드를 함께 사용해서 null 대신에 다른 문자열을 출력하고 싶을 때 엘비스 연산자 사용
* ?: 예제
fun main(){
var s = Student()
s.name = "참새"
s.displayAddressLength()
s.address = "서울"
s.displayInfo()
}
class Student {
lateinit var name:String
var address:String? = null
fun displayInfo() {
println("이름은: ${name} 입니다")
println("주소는: ${address} 입니다")
}
fun displayAddressLength() {
println("주소의 길이는: ${address?.length ?: "초기화하세요"} 입니다")
}
}
* 출력 결과
주소의 길이는: 초기화하세요 입니다
이름은: 참새 입니다
주소는: 서울 입니다
-> ?: 연산자와 함께 "초기화하세요" 문구를 사용하여 null 대신 "초기화하세요" 문구가 출력됨
배열
* 배열
- 변수를 선언하면 코틀린은 메모리에 띄엄띄엄 랜덤으로 생성, 변수의 위치정보가 연속적이지 않기 때문에 순서가 없음
- 이를 배열을 통해 변수에 순서를 매겨 연속적으로 활용
- 배열은 arrayOf 메소드(키워드) 사용
* 배열 예제
package com.example.myapplication
//Arrays를 사용하기 위해서 불러와야함
import java.util.Arrays
fun main(){
// arrayOf메소드를 호출하면 배열을 리턴
// 1,2,3,4,5 각각을 저장한 변수 5개를 배열형태로 arr에 저장
var arr = arrayOf(1,2,3,4,5)
// Arrays.toString : 배열요소를 모두 출력
println(Arrays.toString(arr))
// 배열의 첫번째 요소에 저장된 값을 출력
// var num1 = 1의 num1과 arr[0]은 동일
// arr[0]은 하나의 변수로 취급할 수 있습니다
// arr은 0~4번방(인덱스)까지 접근할 수 있습니다
println(arr[0])
}
* 출력 결과
[1, 2, 3, 4, 5]
1
-> 인덱스(index) : 배열 내의 각 요소의 순서
* 배열 예제 2
fun main() {
var kors = arrayOf(90, 94, 96)
for((idx, kor) in kors.withIndex()) {
println("${idx}번째 국어 점수는 ${kor}입니다")
}
}
* 출력 결과
0번째 국어 점수는 90입니다
1번째 국어 점수는 94입니다
2번째 국어 점수는 96입니다
-> withIndex() : 위치 정보와 값을 하나로 묶어서 리턴한다.
배우면서 느낀 점
null이 들어가면 안 될 때 무조건 !!(널 단언 연산자)를 사용하는 게 좋은 줄 알았는데 아니었다.. 안전 호출 연산자도 있어서 용도에 맞게 잘 써야겠다. 그리고 코틀린에서 배열 선언과 활용법이 생각보다 간단해서 상당히 좋은 거 같다.
예전에 다른 프로그래밍 언어를 배우면서 배열 파트를 제일 어려워했어서 코틀린에서도 많이 어려울까 봐 걱정했는데 코드 내용이 생각보다 간결하게 문제들 몇 번 풀어보고 복습하다 보면 금방 이해가 될 듯하다.
'Android 앱개발 공부 > TIL(Today I Learned)' 카테고리의 다른 글
[Android] TIL 16일차 (2) | 2024.06.12 |
---|---|
[Android] TIL 15일차 (0) | 2024.06.11 |
[Android] TIL 13일차 (0) | 2024.06.07 |
[Android] TIL 12일차 (0) | 2024.06.05 |
[Android] TIL 11일차 (2) | 2024.06.04 |