ThreadLocalRandom.current().nextInt(0, 360) //0부터 360까지
val diff = Duration.between(
LocalDate.now().atStartOfDay(),
item.checkin.atStartOfDay()
)
Duration.between( ) 두시간의 간격을 계산한다
LocalDate.now().atStartOfDay() 현재 날짜를 현재시간으로 초기화한뒤 해당날짜의 자정으로 설정
item.checkin.atStartOfDay() 체크인의 시작 날짜 설정
diff는 현재 날짜의 자정과 체크인시작 날짜의 자정 사이의 날짜들을 나타낸다
잊지말자
fun dateform(a: Int): LocalDate {
val formatter = DateTimeFormatter.ofPattern("yyyyMMdd")
val x = LocalDate.parse(a.toString(), formatter)
return LocalDate.parse(x.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")))
}
formatter 는 "yyyyMMdd"패턴의 코드스타일을 검사 수정해준다
x는 parse()를 써서 LocalDate객체로 문자열을 파싱해준다
파싱:문자열을 원하는 형식의 데이터로 변환하는 과정
입력받은 8자리 문자열이 "yyyyMMdd"패턴을 가진게 x
x를 다시 포맷해서 패턴을 "yyyy-MM-dd"로 변환해준다
with 함수는 Kotlin에서 제공하는 표준 라이브러리 함수 중 하나로, 특정 객체에 대한 일련의 작업을 수행할 때 사용
예시)
data class Person(var name: String, var age: Int)
fun main() {
val person = Person("John", 30)
// with 함수를 사용하여 person 객체의 멤버에 직접 접근
with(person) {
println("현재 이름: $name")
println("현재 나이: $age")
// person 객체의 멤버 수정
name = "Jane"
age = 25
println("수정된 이름: $name")
println("수정된 나이: $age")
}
// with 블록을 빠져나왔을 때의 person 객체 상태
println("최종 이름: ${person.name}")
println("최종 나이: ${person.age}")
}
with(peopleList.find { it.name == a }) {
if (this == null) {
println("예약된 사용자를 찾을 수 없습니다.")
} else {
for (i in peopleList) {
if (i.name == this.name) {
sumcash += i.cash
sumprice += i.price
sumbal += i.balance
}
}
peopleList안에 name이 a랑 같은 원소 리스트(peopleList[a이름같은거])를 this로 표현한다
csv라고만 적었지만 아마 모든 텍스트 파일은 될것같다
println("영수증 내보내실 분의 성함을 입력해주세요")
val name = readln()
val filename = "C:\\Users\\zaq86\\OneDrive\\바탕 화면\\Velogimg\\$name 님 예약 영수증.csv"
val sortedArray = reserveList.sortedBy { item -> item.people.name }//이름순으로 정렬
try {
File(filename).printWriter().use { out ->
//헤더 작성
out.println("Name, RoomNumber, CheckIn, CheckOut, Price")
sortedArray.forEach { it ->
out.println("${it.people.name},${it.roomnum},${it.checkin},${it.checkout},${it.price}")
}
}
println("영수증이 성공적으로 내보내졌습니다. 파일 경로: $filename")
}catch (e: Exception) {
println("에러 발생: $e")
}
File(경로) File클래스를 이용해서 지정된 파일 경로에대한 파일 객체를 생성
printWriter 로 파일에 직접 문자열을 쓸 수 있다
.use로 블록을 정의하고 out은 printWriter객체를 나타낸다
println으로 헤더를 정의하고 그밑으로 forEach를 사용해 sortedArray를 순회해서 정보를 나열한다
파일만들기(경로).파일내용입력하기{
내용
}
- Kotlin의 널 세이프티 방법 - Null 예외로부터 안전한 설계를 위한 다양한 키워드들을 지원해요 - 코틀린은 ?, !!, ?., ?: 로 Null예외로부터 살아남으려고 해요 - 하지만 강제로 null이 아니라고하는 !!는 최대한 사용을 지양해주세요!
? -> null저장할수도있어
!! -> 절대 null아님
?.키워드 Null이 아닐때만 실행되는 메소드
class Archer : Character {
var name:String
var age:Int
var gender:String
var money:Int
var hp:Int
constructor(_name:String, _age:Int, _gender:String, _money:Int, _hp:Int) {//생성자 <- 코틀린이 컴파일하는 시점에서 생성자가 있으면 객체는 만들어짐
name = _name //여기서 이미 초기화하니까 위에 class var들을 초기화 할 필요가 없음
age = _age
gender = _gender
money = _money
hp = _hp
println("${name}궁수 생성") //궁수를 초기화하기전에 생성한다면 위에 class에 있는 변수들을 초기화해줄 필요가 있음
}
Arrays 배열의 요소 전부
Arrays는 외부 패키지에 있는 클래스를 임포트해야함 //java.uill.Arrays
// arrayOf메소드를 호출하면 배열을 리턴해줍니다
// 1,2,3,4,5 각각을 저장한 변수 5개를 배열형태로 arr에 저장합니다
var arr = arrayOf(1,2,3,4,5)
// 배열요소를 모두 출력합니다
println(Arrays.toString(arr))
// 배열의 첫번째 요소에 저장된 값을 출력합니다
// var num1 = 1의 num1과 arr[0]은 동일합니다
// arr[0]은 하나의 변수로 취급할 수 있습니다
// arr은 0~4번방(인덱스)까지 접근할 수 있습니다
println(arr[0])
출력 [1, 2, 3, 4, 5] 이런식으로 나옴
List 배열(array)와 달리 크기가 정해져있지 않다
listOf 읽기전용
mutableListOf 수정가능
ArrayList<자료형> mutable이랑 비슷하지만 배열형태로 저장
// 읽기전용 맵입니다
// 변수명[키]로 데이터에 접근할 수 있습니다
var scoreInfo1 = mapOf("kor" to 94, "math" to 90, "eng" to 92)
println(scoreInfo1["kor"])
// 수정가능 맵입니다
// 변수명[키]로 데이터에 접근할 수 있습니다
var scoreInfo2 = mutableMapOf("kor" to 94, "math" to 90)
scoreInfo2["eng"] = 92
println(scoreInfo2["eng"])
// 맵의 키와 값을 동시에 추출해서 사용할 수 있습니다
for((k,v) in scoreInfo2) {
println("${k}의 값은 ${v}입니다")
}
for( in ) { } 자주 쓰니까 잘 이해하자
set은 순서가 없고 중복없이 데이터를 관리함
다른 컬렉션들은 요소를 찾는데
집중하지만 set은 요소가 존재
하는지가 중요
// 읽기전용 Set입니다.
var birdSet = setOf("닭", "참새", "비둘기")
// 수정가능 Set입니다.
var mutableBirdSet = mutableSetOf("닭", "참새", "비둘기")
mutableBirdSet.add("꿩")
mutableBirdSet.remove("꿩")
println("집합의 크기는 ${birdSet.size} 입니다")
var findBird = readLine()!!
if(birdSet.contains(findBird)) {
println("${findBird} 종류는 존재합니다.")
} else {
println("${findBird}는 존재하지 않습니다.")
}
contains( ) 메소드는 컬렉션에 지정된 요소가 포함되어있는지 확인
// 귀여운 새의 집합
var birdSet = setOf("닭", "참새", "비둘기", "물오리")
// 날수있는 새의 집합
var flyBirdSet = setOf("참새", "비둘기", "까치")
// 모든 새의 집합 (합집합)
var unionBirdSet = birdSet.union(flyBirdSet)
// 귀엽고 날수있는 새의 집합 (교집합)
var intersectBirdSet = birdSet.intersect(flyBirdSet)
// 귀여운 새들중에서 날수없는 새의 조합 (차집합)
var subtractBirdSet = birdSet.subtract(flyBirdSet)
println("=====합집합=====")
println("모든 새의 집합 : ${unionBirdSet}")
println("=====교집합=====")
println("귀엽고 날수있는 새의 집합 : ${intersectBirdSet}")
println("=====차집합=====")
println("귀엽고 날수없는 새의 집합 : ${subtractBirdSet}")
union 합집합 intersect 교집합 subtract 차집합
💡 람다식을 이용해서 메소드를 간결하게 정의할 수 있다
fun add(num1:Int, num2:Int, num3:Int) = (num1+num2+num3)/3
var add = {num1: Int, num2: Int, num3: Int -> (num1+num2+num3) / 3}
println("평균값은 ${add(10,20,30)}입니다")
💡 메모리 전역에서 유일한 객체임을 보장 받는다
- 설명
- 보통 객체는 자원이 가능한 만큼 생성할 수 있어요
- 각각의 객체는 상이한 위치정보를 가지고 있어서 저장하는 값도 객체마다 고유해요
- 싱글턴을 활용하면 해당 객체는 메모리 전역에서 유일함을 보장하고 위치정보가 고정이예요
- 프로그램이 실행되는 시점에 메모리에 바로 로드해서 위치를 잡아요
- Kotlin의 싱글턴 구현방법
- 코틀린은 companion, object 키워드로 싱글턴을 구현할 수 있어요
그래서 왜 필요?
다른 클래스들에서 쉽게 접근함
전역에서 공통적으로 사용하는 정보라면 메모리를 더욱 효율적으로 활용
객체 자원간의 충돌을 방지
fun main() {
// trash와 같이 생성자에 매개변수 전달 가능
var singletonObject1 = MySingletonClass.getInstance(trash = 1)
singletonObject1.setNum(5)
println("num값은: ${singletonObject1.getNum()}")
// singletonObject2에서 num을 10으로 대입
var singletonObject2 = MySingletonClass.getInstance(trash = 1)
singletonObject2.setNum(10)
// singletonObject1의 num이 10으로 출력됨
// singletonObject1과 singletonObject2는 같은 객체를 공유하기 때문
println("num값은: ${singletonObject1.getNum()}")
}
class MySingletonClass private constructor() {
private var num:Int = 0
companion object {
@Volatile private var instance: MySingletonClass? = null
private var trash = 0
fun getInstance(trash: Int): MySingletonClass {
this.trash = trash
// 외부에서 요청왔을때 instance가 null인지 검증
if(instance == null) {
// synchronized로 외부 쓰레드의 접근을 막음
// 쓰레드는 다음챕터에서 소개합니다!
// 쓰레드간의 객체상태 혼돈을 막기위해 사용한다고 이해해주세요
synchronized(this) {
instance = MySingletonClass()
}
}
return instance!!
// 엘비스연산자와 뒷장에서배울 scope function을 이용하면
// 아래와같이 더욱 직관적인 코드 작성이 가능합니다
// return instance ?: synchronized(this) {
// // also는 호출한 객체를 it으로 넘김
// // instance가 null이라면 새로 생성하고 아니면 무시함
// instance ?: MySigletonClass().also {
// instance = it
// }
// }
}
}
fun setNum(num: Int) {
this.num = num
}
fun getNum(): Int{
return this.num
}
}
클래스가 다른대 클래스호출없이 오버라이드 없이 getInstance 불러옴
fun main() {
println("몇 마리를 생성하시겠습니까?")
var count = readLine()!!.toInt()
var birds = mutableListOf<Bird>()
for(idx in 0..count-1) {
println("조류의 이름을 입력해주세요")
var name = readLine()!!
birds.add(Sparrow(name) as Bird)
}
println("============조류 생성완료============")
for(bird in birds) {
bird.fly()
}
// 다운캐스팅 오류
// Sparrow는 Bird가 가져야할 정보를 모두 가지고 있지 않기 때문임
// var s1:Sparrow = birds.get(0)
}
open class Bird(name: String) {
var name: String
init {
this.name = name
}
fun fly() {
println("${name}이름의 조류가 날아요~")
}
}
class Sparrow(name: String): Bird(name) {
}