
코틀린 교육은 오늘로 종료
과제 제출하는데 클래스에 lateinit을 사용해보려고 자동차 객체 프로퍼티에 lateinit을 붙여줬는데 lateinit은 생성자나 init블럭이 아닌 메서드에서 나중에 값을 할당할때 사용하는거라 사실 필요없는 부분이었다. 너무부끄럽다...
대부분의 언어에서
순서를 가진 값의 묶음은 [ ] 대괄호로
순서가 없는 값의 묶음은 { } 중괄호로 표현됨
국제 표준은 아니지만 대부분 이 규칙을 따르고 있음
컬렉션 중 set은 생략했음
몽키테스트
알파테스트 - 기획된 기능 테스트
베타테스트(내부)
베타테스트(클로즈) - 버그 테스트
베타테스트(오픈) - 홍보 목적이 큼(버그가 거의 없어야 함)
유튜버에 클로즈베타 테스트 비용 2~3천 많으면 5천 이상~
일반 홍보비용보다 더 싸게 먹힌다고 함
fun main() {
// 문자열 생성
// String 클래스의 생성자에
// StringBuffer, StringBuilder, ByteArray, CharArray
// 를 넣어주면 가지고 있는 글자 데이터를 이용해
// 문자열을 생성한다.
val array1 = CharArray(5){
'a'
}
val str1 = String(array1)
println("str1 : $str1")
// ""로 묶어준 것도 String 객체를 생성한 것이다.
val str2 = "안녕하세요"
// 원하는 n번째의 글자를 가져올 수 있다.
println("str2[0] : ${str2[0]}")
println("str2[1] : ${str2[1]}")
// 원하는 n번째의 글자를 변경하는건 불가
// str1[0] = 'A'
// 원하는 부분의 글자들을 추출하여 새로운 문자열로 생성한다.
// 순서값을 지정한다.
val str3 = str2.substring(1..3) // 두번째~네번째
println("str3 : $str3")
}
str1 : aaaaa
str2[0] : 안
str2[1] : 녕
str3 : 녕하세
fun main() {
// 문자열 비교
val str4 = "Hello World"
val str5 = "hello world"
val str6 = "Hello World"
// == : 자바에서는 문자열 객체의 주소값을 비교하지만
// 코틀린에서는 문자열 값 자체를 비교함(코틀린에서 == 연산자를 사용 시 equals 메서드가 호출됨)
if(str4 == str5){
println("str4와 str5는 같습니다")
}else{
println("str4와 str5는 다릅니다")
}
if(str4 == str6){
println("str4와 str6는 같습니다")
}else{
println("str4와 str6는 다릅니다")
}
}
str4와 str5는 다릅니다
str4와 str6는 같습니다
fun main() {
// 문자열 비교
val str4 = "Hello World"
val str5 = "hello world"
val str6 = "Hello World"
println(str4.compareTo(str5))
println(str4.compareTo(str6))
// compareTo의 두 번째 매개변수에 true 를 넣어주면
// 모두 소문자로 변환하여 계산해준다.
println(str4.compareTo(str5,true))
}
-32
0
0
fun main() {
// 문자열 비교
val str4 = "Hello World"
val str5 = "hello world"
val str6 = "Hello World"
// equals 메서드의 두 번째 매개변수애 true를 넣어주면 대소문자를 무시하고 같은지 비교해준다.
if(str4.equals(str5, true)){
println("두 문자열은 대소문자를 무시하면 같습니다.")
}
}
두 문자열은 대소문자를 무시하면 같습니다.
fun main() {
// 구분자를 기준으로 문자열을 나눈다.
val str7 = "ab_cd ef_gh"
// 띄어쓰기를 기준으로 나눈다.
val r6 = str7.split(" ")
println("r6 : $r6")
for(temp6 in r6){
println(temp6)
}
}
r6 : [ab_cd, ef_gh]
ab_cd
ef_gh
fun main() {
// uppercase : 소문자를 대문자로 하는 문자열을 생성한다.
// lowercase : 대문자를 소문자로 하는 문자열을 생성한다.
val str8 = str4.uppercase()
val str9 = str4.lowercase()
println("str8 : $str8")
println("str9 : $str9")
}
str8 : HELLO WORLD
str9 : hello world
fun main() {
// startsWith : ~로 시작하는지
// endsWith : ~로 끝나는지
val r10 = str4.startsWith("H")
val r11 = str4.startsWith("A")
val r12 = str4.endsWith("d")
val r13 = str4.endsWith("A")
println("r10 : $r10")
println("r11 : $r11")
println("r12 : $r12")
println("r13 : $r13")
}
r10 : true
r11 : false
r12 : true
r13 : false
fun main() {
// 글자의 개수를 반환한다.
println("str4의 글자수 : ${str4.length}")
}
str4의 글자수 : 11
fun main() {
// 문자열 좌우 공백을 제거
val str20 = " aaa "
println("[${str20}]")
println("[${str20.trim()}]")
}
[ aaa ]
[aaa]
fun main() {
// 리스트 생성
// 불변형 리스트
// 리스트 생성 이후 값의 추가, 수정, 삽입, 삭제 등이 불가능하다.
val list1 = listOf(10, 20, 30, 40, 50)
println("list1 : $list1")
val list2 = listOf("문자열1", "문자열2", "문자열3")
println("list2 : $list2")
// 타입이 달라도 된다.
val list3 = listOf(100, 11.11, "문자열", true)
println("list3 : $list3")
}
list1 : [10, 20, 30, 40, 50]
list2 : [문자열1, 문자열2, 문자열3]
list3 : [100, 11.11, 문자열, true]
fun main() {
// 수정 가능한 리스트 ArrayList로 생성된다.
// 텅 비어있는 수정 가능한 리스트를 생성 : 나중에 객체를 추가할 수 있게
val list4 = mutableListOf<Int>()
// 생성시 관리할 객체를 지정할 수 있다.
val list5 = mutableListOf("문자열1","문자열2","문자열3")
println("list4 : $list4")
println("list5 : $list5")
}
list4 : []
list5 : [문자열1, 문자열2, 문자열3]
fun main() {
// 비어있는 수정 불가능한 리스트
val list6 = emptyList<Int>()
println("list6 : $list6")
}
list6 : []
fun main() {
// null이 있을 경우(수정 불가능)
// null 포함
val list7 = listOf(10, 20, null, 40, null, 60, 70)
// null 포함하지 않음
val list8 = listOfNotNull(10, 20, null, 40, null, 60, 70)
println("list7 : $list7")
println("list8 : $list8")
}
list7 : [10, 20, null, 40, null, 60, 70]
list8 : [10, 20, 40, 60, 70]
fun main() {
val list1 = listOf(10, 20, 30, 40, 50)
// for 문 사용
for(item in list1){
println("item : $item")
}
}
item : 10
item : 20
item : 30
item : 40
item : 50
fun main() {
val list1 = listOf(10, 20, 30, 40, 50)
// 관리하는 객체의 개수
println("list size : ${list1.size}")
}
list size : 5
fun main() {
val list1 = listOf(10, 20, 30, 40, 50)
// 관리하는 객체에 접근한다.
// [ ] 연산자를 통해 순서값(0부터 1씩 증가)를 지정하여 접근한다.
println("list1 0 : ${list1[0]}")
println("list1 1 : ${list1[1]}")
val list9 = listOf(10, 20, 30, 10, 20, 30)
// 지정한 객체가 앞에서 부터 몇 번째에 있는가
val index1 = list9.indexOf(20)
println("index1 : $index1")
// 지정한 객체를 뒤에서부터 찾아서 앞에서 부터 몇번째에 있는가
val index2 = list9.lastIndexOf(20)
println("index2 : $index2")
// indexOf, lastIndexOf 모두 없는 것을 지정하면 -1을 반환한다.
val index3 = list9.indexOf(100)
println("index3 : $index3")
// 일부를 발췌하여 새로운 리스트를 생성한다.
// 순서값 1 ~ 3-1 까지
val list10 = list9.subList(1, 3)
println("list10 : $list10")
}
list1 0 : 10
list1 1 : 20
index1 : 1
index2 : 4
index3 : -1
index4 : -1
list10 : [20, 30]
fun main() {
val list21 = mutableListOf(10, 20, 30)
// 객체를 추가한다.
// 리스트 뒤에 추가된다.
list21.add(40)
list21.add(50)
list21.addAll(listOf(60,70,80,90,100))
println("list21 : $list21")
}
list21 : [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
fun main() {
val list20 = listOf(10, 20, 30)
// 수정 불가능한 리스트에 추가
// 추가, 수정, 삭제, 삽입 등과 관련된 메서드 자체가 없다.
list20.add(40) // 에러
}
fun main() {
val list21 = mutableListOf(10, 20, 30)
// 삽입
// add 메서드를 이용할 때 위치를 지정하면 그 위치에 삽입된다.
// add(순서값, 객체) : 순서값에 해당하는 위치에 객체를 삽입하고 그 이후의 객체들을 뒤로 밀린다.
list21.add(1, 100)
println("list21 : $list21")
}
list21 : [10, 100, 20, 30]
fun main() {
val list21 = mutableListOf(10, 20, 30)
list21.add(1, 100)
// 삽입할 데이터가 다수라면 addAll을 사용한다.
list21.addAll(3, listOf(2000,3000,4000,5000))
println("list21 : $list21")
}
list21 : [10, 100, 20, 2000, 3000, 4000, 5000, 30]
fun main() {
val list21 = mutableListOf(10, 20, 30)
// 값을 수정한다.
// 두 번째 값을 1000으로 덮어 씌운다.
list21.set(1, 1000)
println("list21 : $list21")
list21[1] = 10000
println("list21 : $list21")
}
list21 : [10, 1000, 30]
list21 : [10, 10000, 30]
fun main() {
val list21 = mutableListOf(10, 20, 30)
list21[1] = 10000
// 제거
// 지정한 값을 제거한다.
list21.remove(10000)
println("list21 : $list21")
// 없는 객체를 제거할 경우
// 오류가 발생하지 않고 아무런 일도 일어나지 않음
list21.remove(50000)
println("list21 : $list21")
}
list21 : [10, 30]
list21 : [10, 30]
fun main() {
val list21 = mutableListOf(10, 20, 30)
// 여러 객체를 지정하여 제거한다.
list21.removeAll(listOf(10, 30))
println("list21 : $list21")
}
list21 : [20]
fun main() {
val list21 = mutableListOf(10, 20, 30)
// 위치를 지정하여 제거한다.
// 두 번째 객체를 제거한다.
list21.removeAt(1)
println("list21 : $list21")
}
list21 : [10, 30]
fun main() {
val list21 = mutableListOf(10, 20, 30)
// 모두 삭제
list21.clear()
println("list21 : $list21")
}
list21 : []
fun main() {
val list100 = listOf(10, 20, 30, 40, 50)
// list안에 저장되어 있는 객체를 추출하여 새로운 mutable list를 생성한다.
val list200 = list100.toMutableList()
list200.add(60)
println("list200 : $list200")
}
list200 : [10, 20, 30, 40, 50, 60]
fun main() {
val list100 = listOf(10, 20, 30, 40, 50)
val list200 = list100.toMutableList()
list200.add(60)
// mutable list 안에 저장되어 있는 객체를 추출하여 새로운 list를 생성한다.
val list300 = list200.toList()
// list300.add(70) // mutable이 아니므로 add 사용 불가
println("list300 : $list300")
}
list300 : [10, 20, 30, 40, 50, 60]
fun main() {
// 이름 to 객체 형태로 지정한다.
// 수정 불가능한 map
val map1 = mapOf("key1" to 10, "key2" to 20, "key3" to 30)
println("map1 : $map1")
// 이름은 문자열이 아니어도 된다.
val map2 = mapOf(10 to "문자열1", 20 to "문자열2", 30 to "문자열3")
println("map2 : $map2")
}
map1 : {key1=10, key2=20, key3=30}
map2 : {10=문자열1, 20=문자열2, 30=문자열3}
fun main() {
// 수정 가능한 맵
val map3 = mutableMapOf("key1" to 10, "key2" to 20, "key3" to 30)
println("map3 : $map3")
}
map3 : {key1=10, key2=20, key3=30}
fun main() {
// 다양한 타입의 값을 담을 수 있다.
val map4 = mapOf("key1" to 10, "key2" to 11.11, "key3" to "문자열")
println("map4 : $map4")
}
map4 : {key1=10, key2=11.11, key3=문자열}
fun main() {
// 제네릭을 설정할 수 있다
// map은 제네릭을 설정하지 않아도 되지만 딱 한 경우에는 무조건 설정해야 한다.
// 한가지 타입의 객체를 담는 맵
// <이름으로 사용할 객체의 클래스타입, 저장할 객체의 클래스타입>
val map5 = mapOf<String, Int>("key1" to 10, "key2" to 20, "key3" to 30)
println("map5 : $map5")
// 다양한 타입의 객체를 담는 맵
val map6 = mapOf<String, Any>("key1" to 10, "key2" to 11.11, "key3" to "문자열")
println("map6 : $map6")
// 텅 비어있는 맵을 만들때는 반드시 제네릭을 설정해야 한다.
val map7 = mapOf<String, Int>()
val map8 = mutableMapOf<String, Any>()
}
map5 : {key1=10, key2=20, key3=30}
map6 : {key1=10, key2=11.11, key3=문자열}
fun main() {
// 관리하고 있는 객체를 추출한다.
val map9 = mapOf("key1" to 10, "key2" to 20, "key3" to 30)
val map10 = mutableMapOf("key1" to 10, "key2" to 20, "key3" to 30)
// get 메서드 사용
println("map9 key1 : ${map9.get("key1")}")
println("map10 key1 : ${map10.get("key1")}")
}
map9 key1 : 10
map10 key1 : 10
fun main() {
// 관리하고 있는 객체를 추출한다.
val map9 = mapOf("key1" to 10, "key2" to 20, "key3" to 30)
val map10 = mutableMapOf("key1" to 10, "key2" to 20, "key3" to 30)
// [ ] 사용
println("map9 key1 : ${map9["key1"]}")
println("map10 key1 : ${map10["key1"]}")
}
map9 key1 : 10
map10 key1 : 10
fun main() {
val map1 = mapOf("key1" to 10, "key2" to 20, "key3" to 30)
// 관리하는 객체의 개수
println("map1 size : ${map1.size}")
// 이름들을 가져온다.
println("map1 keys : ${map1.keys}")
// 관리하는 객체들을 가져온다.
println("map1 values : ${map1.values}")
// 이 이름으로 저장된 객체가 있는지
val chk1 = map1.containsKey("Key1")
val chk2 = map1.containsKey("Key100")
println("chk1 : $chk1")
println("chk2 : $chk2")
}
map1 size : 3
map1 keys : [key1, key2, key3]
map1 values : [10, 20, 30]
chk1 : false
chk2 : false
chk3 : true
chk4 : false
fun main() {
val map12 = mutableMapOf("a1" to 10, "a2" to 20)
println("map12 : $map12")
// 추가
map12.put("a3", 30)
println("map12 : $map12")
// 없는 이름으로 객체를 넣어주면 추가된다.
map12["a4"] = 40
println("map12 : $map12")
}
map12 : {a1=10, a2=20}
map12 : {a1=10, a2=20, a3=30}
map12 : {a1=10, a2=20, a3=30, a4=40}
fun main() {
val map12 = mutableMapOf("a1" to 10, "a2" to 20)
println("map12 : $map12")
// 수정
// 있는 이름으로 객체를 넣어준다
map12["a2"] = 400
println("map12 : $map12")
}
map12 : {a1=10, a2=20}
map12 : {a1=10, a2=400}
fun main() {
val map12 = mutableMapOf("a1" to 10, "a2" to 20)
println("map12 : $map12")
// 삭제
map12.remove("a2")
println("map12 : $map12")
}
map12 : {a1=10, a2=20}
map12 : {a1=10}
fun main() {
// mapOf -> mutableMapOf
val map13 = mapOf("a1" to 10, "a2" to 20, "a3" to 30)
val map14 = map13.toMutableMap()
map14["a4"] = 40
println("map14 : $map14")
}
map14 : {a1=10, a2=20, a3=30, a4=40}
fun main() {
val map13 = mapOf("a1" to 10, "a2" to 20, "a3" to 30)
// mutableMap -> map
val map15 = map13.toMap()
// map15["a5"] = 50 // 에러
println("map15 : $map15")
}
map15 : {a1=10, a2=20, a3=30}
fun main() {
// 배열
var array1 = arrayOf(10, 20, 30, 40, 50)
// for
// 배열이 관리하는 객체의 수 만큼 반복하면서
// 반복하는 n번째의 객체를 v1에 담아준다.
for(v1 in array1){
println("array1 v1 : $v1")
}
println()
// 배열이 관리하는 데이터의 개수 만큼 람다식을 반복한다.
// it에는 반복하는 n번째의 데이터가 들어온다.
array1.forEach {
println("array1 it : $it")
}
}
array1 v1 : 10
array1 v1 : 20
array1 v1 : 30
array1 v1 : 40
array1 v1 : 50
array1 it : 10
array1 it : 20
array1 it : 30
array1 it : 40
array1 it : 50
fun main() {
// list
val list1 = listOf(10, 20, 30, 40, 50)
list1.forEach {
println("list1 it : $it")
}
}
list1 it : 10
list1 it : 20
list1 it : 30
list1 it : 40
list1 it : 50
fun main() {
// map
val map1 = mapOf("a1" to 10, "a2" to 20)
map1.forEach{
println("map1 key : ${it.key}")
println("map1 value : ${it.value}")
}
}
map1 key : a1
map1 value : 10
map1 key : a2
map1 value : 20
try {
예외가 발생할 가능성이 있는 코드
} catch (e:예외클래스) {
예외가 발생했을때 수행할 코드
} finally {
예외 발생 여부에 관계없이 수행해야 하는 코드
}
try : 개발자가 구현하는 코드 부분
catch : try 부분에서 예외가 발생했을 때 동작하는 코드
try 부분에서 예외가 발생되면 try 부분의 수행은 중단되고 catch부분으로 넘어간다.
예외가 발생되면 VM은 프로그램을 강제 종료시킨다.
예외 처리의 목적은 예외 발생 시 프로그램이 강제 종료되지 않도록 하고 catch에 작성한 코드가 동작될 수 있도록 함에 있다.
오류가 나는 경우
fun main() {
val a1 = 10 / 0
val str:String? = null
println(str!!.length)
val str2 = "안녕하세요"
val a2:Int = str2.toInt()
}
fun main() {
try {
// val a1 = 10 / 0
// val str:String? = null
// println(str!!.length)
val str2 = "안녕하세요"
val a2:Int = str2.toInt()
}catch(e:Exception){
e.printStackTrace()
}
println("이 부분이 수행 될까요?")
}
java.lang.NumberFormatException: For input string: "안녕하세요"
at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67)
at java.base/java.lang.Integer.parseInt(Integer.java:668)
at java.base/java.lang.Integer.parseInt(Integer.java:784)
at MainKt.main(main.kt:25)
at MainKt.main(main.kt)
이 부분이 수행 될까요?
fun main() {
try {
val a1 = 10 / 0
val str:String? = null
println(str!!.length)
val str2 = "안녕하세요"
val a2:Int = str2.toInt()
}catch(e:ArithmeticException){ // 10을 0으로 나눴을 때의 예외 처리
// e.printStackTrace()
println("수학오류가 발생하였습니다")
}catch (e:NullPointerException){ // null을 가진 변수를 통해 객체에 접근하려고 했을 때의 예외 처리
println("NULL 접근 오류가 발생하였습니다")
}catch (e:NumberFormatException){ // 숫자로 변환할 수 없는 문자열을 숫자로 변환하고자 할 때의 예외 처리
println("숫자 양식 오류가 발생하였습니다")
}catch (e:Exception){ // 그 밖의 모든 예외에 대한 처리
println("그 밖의 오류가 발생하였습니다")
}
println("이 부분이 수행 될까요?")
}
수학오류가 발생하였습니다
이 부분이 수행 될까요?
개발 패턴
개발 프레임워크라고 부르기도 한다.
개발과 유지보수를 용이하게 하기 위해 각 파일마다 역할을 지정하고
그 역할에 맞는 기능을 구현하도록 하는 것
학생 정보를 관리하는 프로그램
처음 시작하면 메뉴를 보여준다.
[ 메인 메뉴 ]
1. 학생 정보 입력
2. 학생 정보 검색
3. 학생 정보 전체 출력
4. 각 과목별 총점과 평균 확인
5. 종료
번호를 입력해주세요 :
메인 메뉴에서 1번을 선택하면
현재 입력된 학생 수 : 10명
학생 이름 :
학생 나이 :
국어 점수 :
영어 점수 :
수학 점수 :
입력이 완료되면 메인 메뉴를 보여준다.
메인 메뉴에서 2번을 선택하면
검색할 학생 이름 :
학생 이름 : 0000
학생 나이 : 0000
국어 점수 : 0000
영어 점수 : 0000
수학 점수 : 0000
메인 메뉴를 보여준다.
메인 메뉴에서 3번을 선택하면
학생 이름 : 0000
학생 나이 : 0000
국어 점수 : 0000
영어 점수 : 0000
수학 점수 : 0000
위와 같은 형태로 모든 학생들의 정보를 보여주고 메인 메뉴를 보여준다.
메인 메뉴에서 4번을 선택하면
국어 총점 : 0000
영어 총점 : 0000
수학 총점 : 0000
국어 평균 : 0000
영어 평균 : 0000
수학 평균 : 0000
메인 메뉴를 보여준다.
메인 메뉴에서 5번을 입력하면
"프로그램이 종료되었습니다." 를 보여주고 프로그램 종료한다.
학생들의 정보는 모두 파일로 저장한다.

com.lion.project1.controller : 컨트롤러를 모아놓은 패키지
com.lion.project1.model : Model 들을 모아놓은 패키지
com.lion.project1.view : View 들을 모아놓은 패키지
com.lion.project1.dao : 데이터를 저장하고 읽어오는 클래스들을 모아놓은 패키지
com.lion.project1.activity : 각 상태에 대한 클래스들을 모아놓은 패키지
com.lion.project1.util : 기타 역할을 수행하는 클래스나 인터페이스를 모아놓은 패키지
※ 출처 : 멋쟁이사자 앱스쿨 2기, 소프트캠퍼스