문법적인 주요 특징 소개
1.문장의 끝을 나타내는 ; 를 사용하지 않는다, 써도 에러는 아님 무시됨
2.변수를 만들 때 자료형을 먼저 쓰지 않고 var / val 키워드 사용함 단, 자료형 존재, 자동 형변환 안됨 즉 정적타입 언어임
( cf : 자바스크립, 파이썬 = 동적 타입 언어 )
3. new 키워드 없이 객체 생성 new String() --> String
4.안전하게 null을 다룰 수 있는 문법 제공됨 (null safty)
5.코틀린은 함수형 언어이다. 즉, 함수를 객체처럼 변수에 저장하고 파라미터로 넘겨주는 등의 작업이 가능하다
package com.bsj0420.ex01kotlinhello
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.TextView
import android.widget.Toast
//코틀린에서 class 상속 관련 키워드 => :
//상속하는 클래스명 옆에 주 생성자를 호출하는 ()가 필수임
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) { //변수명 : 자료형
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//대략적인 코틀린의 코딩방식 살펴보기 - 자바와의 차이점 기반으로..
//변수는 var 키워즈 사용
var btn:Button = findViewById(R.id.btn)
//버튼에 클릭 이벤트 달길 - 자바의 람다식과 비슷한 SAM 변환
btn.setOnClickListener{
clickBtn()
}
}
//코틀린에서의 메소드(함수) fun 키워드 사용
private fun clickBtn() {
var tv = findViewById<TextView>(R.id.tv) // :자료형을 생략하면 제네릭으로 표시해줘야함
//tv.setText("Nice")
//코틀린에서는 setXxx() 메소드를 권장하지 않고 멤버변수에 값 대입을 더 선호한다
tv.text = "Nice to meet you" //내부적으로 겟터 셋터를 함
}
//오버라이드 메소드가 Java에서는 @Overrride라는 어노테이션 사용했지만
//코틀린에서는 메소드 앞에 override 키워드 삽입 -> override 안쓰면 error
//오버라이드 메소드 앞에 명시적으로 override키워드 없으면 에러
override fun onResume() {
super.onResume()
//코틀린에서는 소문자로 Taost를 써야 자동완성된다
Toast.makeText(this, "onResume", Toast.LENGTH_SHORT).show()
}
}
fun main(){
//.kt 코틀린 파일만 별도로 실행하려면 마우스의 우클릭으로
//해당 파일 run메뉴 실행 => 결과는 하단 [run] 탭에 표됨
//1. 화면(콘솔창 - run 탭)에 출력 : print(), println()
print("안녕")
print(10.5)
println()
println("반가워")
println("Hi kotlin")
println(5+3)
//변수명을 전달하면 변수 안에 값이 출력
var a:Int = 10
println(a)
var b = "Hello"
println(b)
}
💡 기본 자료형 크기 순서
Boolean < Byte < Char < Short < Int < Long < Float
package com.bsj0420.ex01kotlinhello
// # 프로그램의 시작함수인 main함수가 반드시 있어야함.
fun main(){
//2. 자료형과 변수
//코틀린 자료형의 종류
//1) 기초 타입 : Boolean < Byte < Char < Short < Int < Long < Float < Double
// 기본적으로 코틀린은 모든 변수가 참조형 (메모리 8byte)
// 코틀린은 Wapper 클래스만 존재 (Wapper면서 기본형)
//2) 참조타입 : String, Random, Any(자바의 Object와 비슷), Unit .. 그 외 코틀린용 APIs, 자바 APIs
//변수의 2가지 종류 : var (varalbe) , val (value) [문법 -> var 변수명:자료형, val 변수명:자료형]
//2-1) var : 값 변경 가능한 변수
var num:Int = 50
println(num)
var num2:Double = 3.14
println(num2)
//권장하지는 않지만 변수를 만들 때 값을 초기화 하지않아도 된다. (단, 지역변수만!)
var num3:Float //Can be joined with assignment
num3 = 5.24f
println(num3)
//변수이므로 변수가 가지고 있는 값 변경 가능
num = 20
println(num)
//자료형이 정해진 변수이므로 다른 자료형 대입은 ERROR
//num = 3.14 //ERROR [Int변수에 Double 대입]
//num2 = 5; // ERROR - [Doble변수에 Int대입] : 자동 형변환 불가능
//명시적으로 형변화하여 값 대입
// ~.toXXX()로 변환 가능 (기초 타입들(8개)만 사용 가능)
num = 3.14.toInt()
num2 = 50.toDouble()
println(num) //3
println(num2) //50.0
//문자열 String 객체
var s:String = "Hello"
println(s)
//var s2:String = Stirng("Nice") //Error - 단순 문자열 객체를 생성할 때 String이라는 클래스 생성자 사용 불가
// String 생성자는 Buffer나 Byte 배열을 String객체로 생성 할 때만 사용
//println(s2)
println()
//2-2) val : 값 변경 불가능한 변수 - 읽기전용 변수
//상수는 아님 상수는 [const val] 키워드 사용
val n1:Int = 100
//n1 = 200 //Error
println(n1)
val n2:Boolean = true
println(n2)
//권장하지 않지만 지역변수 선언할 떄 초기화 안해도 되는 특징
val n3:String
n3 = "오 예" //이때 값이 정해짐
//n3 = "노" //Error
println(n3)
println()
// ## var, val 사용 팁
//데이터 가진 변수는 변수 var[ex) name, age , title...]
//객체를 참조하는 변수는 val [ex) TextView, NotificationManager...]
//2-3) 자료형을 생략하면서 변수 선언 가능 - 자료형 자동 추론
var aa = 10 //Int로 추론
println(aa)
var bb = 3.14 //Double로 추론
println(bb)
var cc= 3.15f // float으로 추론
println(cc)
var dd = false //Boolean
println(dd)
var ee = 'a' //Char
println(ee)
var ff = "oh" //String
println(ff)
//변수선언시 자료형 표기는 없지만 대입하면서 자료형 자동 추론
// 즉, 변수는 자료형 존재
//자료형 명시 생략을 통해 자동 추론하려면 변수 선언하면서 반드시 값 대입해야함
//var gg //Error
//gg=50
// ** 정수값 표기릐 특이점
//실생활에서 숫자 3자리마다 , 구분과 비슷한 표기법
var a3 = 5_000_000
println(a3) //출력은 구분자 없이 됨
println()
//2-4) 코틀린에서만 쓰는 자료형
// Any 타입 [자바의 Object처럼 최상위 타입]
//최상위 타입은 어떤 객체든 참조 가능
//편해보이지만 실제 개발할 떄 어떤 자료형인지 예측이 어려워 필요헐때만 사용햐야됨
var v:Any
v = 10
println(v)
v = 3.14 //에러 안남
println(v)
v = "Hello"
println(v)
println()
//2-5) null값에 대한 자료형[null 안정성], 여기서는 특징만,,
// 코틀린은 자료형을 명시하면 null값을 저장할 수 없음
//var nn:Int = null // Error
//기본적으로 null저장할 수 없음
//null값을 가질 수 있는 변수라고 표시할 수 있음 [Nullable 변수]
// ? 를 표시하면 null 을 저장할 수 있음
var nn:Int? = null
var ss:String? = null
println(nn)
println(ss)
//Nullable 변수의 특이점
var sss:String = "Hello"
println(sss.length)
var ssss:String? = "Hello"
//println(ssss.length) //Nullable 변수는 .으로 멤버 사용 불가 -> null일수 있어서
println(ssss?.length) //?.(nullsafe 연산자) : null이 아닐떄만 length 출력함
println()
//////////////////////////////////////////
// ** 화면 출력의 Format 만들기 **
//문자열 결합에 대한 내용
println("Hello " + "kotlin")
// 숫자 타입과 String 타입은 자동결합 안될 수 있다
//println( 10 + "Java" ) //Error : 넘버 타입이 스트링 타입으로 바뀌지않음
//그래서 number 타입을 Stirng으로 변환해서 결합해야됨
println(10.toString() + " Hello" )
//특이점 문자열이 먼저 있으면 결합 됨
println("Hello " + 50)
println()
//변수 2개의 값을 덧셈하여 출력하는 코드
var nnn1:Int = 50
var nnn2:Int = 30
// 50 + 30 = 80 모양으로 포멧팅하여 출력
// println(nnn1 + "+" +nnn2 +"=" + (nnn1+nnn2)) //error
// println(nnn1.toString() + "+" +nnn2 +"=" + (nnn1+nnn2))
// println(""+nnn1 + "+" +nnn2 +"=" + (nnn1+nnn2))
//위 방법 모습 모두 간결하지 않음
//결합 연산으로 포멧팅하면 코드가 지저분함
println(" $nnn1 + $nnn2 = ${nnn1 + nnn2} ")
//[문자열 템플릿] : 이렇게 문자열 안에 $변수명을 사용하는 것
//주의) 변수 옆에 띄쓰 없으면 하나의 변수라고 생각함
println(" ${nnn1}+${nnn2}=${nnn1 + nnn2}") //붙여 쓰기
}
💡 자료형을 체크하는 연산자 is
자바의 instanceof와 같은 기능으로 사용함
Any 타입 식별 체크용으로 쓴다!!
package com.bsj0420.ex01kotlinhello
fun main(){
//3. 연산자 특이점
//숫자 타입들 간에 산술연산은 자동 형변환 수행 [작은것 -> 큰것]
println(10 + 3.14)
//숫자 타입이 아는 것들과는 자동 형변환 안됨
//println(10 + true) //error
//println(10 + 'A') //error
println('A' + 10) //반대는 됨
//println(10.toChar() + 'A')
//자료형을 체크하는 연산자 is
var n =10
if(n is Int) println("n은 Int형 변수다")
//is연산자는 nullable과 non-nullable을 구분하진 않음
var n2:String = "Hello"
if(n2 is String) println("${n2}는 n2은 String형 변수다")
if(n2 is String?) println("${n2}는 n2은 String형 변수다")
//!is도 있음
if(n2 !is String) println("${n2}는 n2은 String형 변수가 아닙니다")
//다른 자료형은 is로 체크하면 문법 에러
//if(n2 is Int) {} //Error
// is는 Any 타입 식별 체크용으로 쓴다!!
var obj:Any
obj = 10
if(obj is Int) println("${obj}는 Int 이다")
else if(obj is Double) println("${obj}는 Double 이다")
//자바의 instanceof와 같은 기능으로 사용함
class Person{
var name:String = "sam"
var age = 20
}
var p = Person() //Person객체 생성한것
println(p.name + " " + p.age)
//is 연산자의 특이점!!!!!!!!!!
//is를 통해 어떤 객체인지 판별되었다면 참인 영역 안에서는 그 객체로 참조변수 인식
var obj2: Any
obj2 = Person()
//obj2.name //error
//obj2 자료형이 Any타입이기 떄문에 멤버변수 name, age 자동완성되지않음
if (obj2 is Person) {
//참인 영역안에서는 obj2 를 Person 참조변수로 인식
println("${obj2.name} - ${obj2.age} ")
}
println()
//비트연산자가 없다 [& | ~ ^]
//대신 연산기능을 가진 메소드가 존재함
//println( 7 | 3) //error
println(7.or(3)) //or 비트 연산
println(7 or 3) //마치 연산자처럼 or 메소드 표기 가능
println()
package com.bsj0420.ex01kotlinhello
fun main(){
//4. 조건문 if, when [swich 문법이 없음]
//4-1) if문 표현식 - if문이나 else문의 마지막 실행문이 변수에 대입될 수 있음
var ss:String
if (10 > 5) {
ss = "Hello"
} else {
ss = "Nice"
}
var sss:String = if(10>5) {
"Hello"
println("aaa")
"Good" //if 영역 안에 조건이 여러개면 마지막 값이 들어옴
} else "nice"
println(sss)
//이런 특징때문에 if문을 코틀린에서는 제어문이라는 대신에 [if표현식]이라고 부름
//그래서 코틀린에서는 삼항연산자 없음 - if표현식으로 대체함
//var str:String = (10>5)?"aaa":"bbb" //Error
var str:String = if(10>5) "aaa" else "bbb"
println(str + "\n")
//4-2) swich문 없어지고 when 문법이 대체함
var h:Any? = null
//switch(h){} // error : switch문법 없음
//⑤
h = 50
when(h){
10-> println("10")
20-> println("20")
//자료형이 다른 경우를 배치해도 됨
"Hello" -> println("Hello 출력")
//변수가 있어도 됨
n -> println("n변수와 값이 같음")
//2개 이상의 조건을 묶을 수 있음
30, 40 -> println("30 or 40")
//switch문의 defaultd의 역할 = else
else -> { //실행문이 여러줄이면 {} 써도 됨
println("ddddd")
println("and")
}
}
println()
//when도 if문처럼 표현식이라서 결과값을 변수에 저장할 수 있다
h = 20
var result = when(h){
10 -> "aaaa"
10 -> "bbbb"
else -> { //표현식과 같이 쓸거라면 무조건 else 써야함
"bad"
println("abbbb") // => kotlin.Unit
}
}
println(result)
println()
//when에 is키워드 연산자 사용 가능
h = 50
when(h) {
is Int -> println("Int 타입 ")
is String -> println("String 타입 ")
else -> println("else")
}
//when을 특정 수식으로 제어
//주의) when 사용문법이 약간 다름 -> when옆에 () 생략
h = 85
when {
//h >=90 && h <=100 -> println("A학점")
h in 90..100 -> println("A학점") // in : 90~100
h >=80 -> println("B학점")
h >=70 -> println("C학점")
h >=60 -> println("D학점")
h >=50 -> println("E학점")
else -> println("F학점")
}
⑤ {} 으로 실행문 여러개 출력 가능한 모습
💡 작성 방법
for(i in 0 .. 5) => 5 포함
for(i in 0 until 5) => 5 미포함
package com.bsj0420.ex01kotlinhello
fun main(){
//5. 반복문 - while, for
//while문은 다른 것이 없음
//for문은 작성하는 문법이 완전 다름
//for(var i=0; i<5, i++) //이런 문법 없음
//0부터 5까지 6실행되는 반복문 작성 - 마지막 번호 포함됨
for (i in 0..5) {
println(i)
}
println()
for (a in 3..10) {
println(a)
}
println()
//제어변수 앞에 var키워드를 추가하면 error
//for(var t in 0 ..4){} //error
//마지막 숫자 전까지 하려면 .. 대신 until 사용
for(i in 0 until 10) {
println(i) //0~9
}
println()
// 2씩 증가 : step
for(i in 0..10 step 2) {
println(i) //0 2 4 6 8 10
}
println()
//값의 감소 : downTo
for(i in 10 downTo 0) println(i)
println()
//2씩 감소 : downTo step
for(i in 10 downTo 0 step 3) println(i)
println()
// ** '@' Label 로 반복문의 종료영역 선택하기 *****(권장 안함)
for (n in 0 .. 5){
if(n==3) break
print("$n ")
}
println()
println()
for (n in 0 .. 5){
print("$n ")
for (x in 0 .. 10) {
if(x == 6) break
print("$x ")
}
println()
}
println()
println()
//@Label로 break위치 선택 - 반복문에선 안씀
KKK@ for (n in 0 .. 5){ // 0 0 1 2 3 4 5
print("$n ")
for (x in 0 .. 10) {
if(x == 6) break@KKK //이너클래스에서 아웃터 클래스 부를 떄 왕왕 쓴다
print("$x ")
}
println()
}
println()
}
☝ 참고) '@' Label
outer에 이름을 달아서 inner에서 onter를 제어한다
package com.bsj0420.ex01kotlinhello
fun main(){
//6. 배열 Array & 컬렉션 Collection
//6-1) 배열 - 요소 개수 변경 불가능한 배열 : Array
//int[] aaa = new int[3]
var aaa = arrayOf(10,20,30) //자료형 자동 추론
//제네릭으로 명시할 때 주의점!!!!
//제네릭 <> 다음에 대입 연산자가 붙어 있으면 error
//var aaa2: Array<Int>= arrayOf(10,20,30) -> error
var aaa2: Array<Int> = arrayOf(10,20,30)
//요소값 출력
println(aaa2[0])
println(aaa2[1])
println(aaa2[2])
println()
//요소값 변경
aaa2[0] = 100 //개수만 못바꾸고 값은 바꿀 수 있음
println(aaa2[0])
println()
//배열의 길이 : size
println("배열의 길이 : ${aaa2.size}") //자바에선 length
println()
//요소값 일일이 접근하기보다 반복문 사용
for (a in 0 until aaa2.size) {
println(aaa2[a])
}
println()
//배열은 어차피 연속된 인덱스 번호의 나열이니까
//마치 자바의 확장된 for문처럼 쓸수 있음
for (t in aaa) { //t는 인덱스가 아님, 요소 값
println(t)
}
println()
//향상된 for문을 쓰면서 index 번호로 반복하고 싶다면
for (i in aaa2.indices) { //index번호 가져오는 거
println("$i : ${aaa2[i]}")
}
println()
//혹시 인덱스와 값을 동시에 가져오고 싶다면
for((i,v) in aaa2.withIndex()){
println(" $i : $v ")
}
println()
// 배열 갹체 멤버안에 요소값 각각을 반복적으로 접근할 때 마다
//{} 안에 있는 코드가 자동으로 발동하는 forEach 기능 있음
//중괄호 안에 it이라는 특별한 변수가 존재
//그 it이 각 요소 참조변수임
aaa2.forEach {
println(it)
}
println()
var bbb:Array<String> = arrayOf("aaa","bbb","ccc")
bbb.forEach {
println(it)
}
println()
//배열을 만들면서 자동추론을 적용할 때 타입을 명시하는데
//기본형 타입일 때 대해서는 별도의 생성 함수가 존재함
var ccc = arrayOf<Int>(1000,2000,3000)
var ddd = intArrayOf(10,20,30) //Int 전용 배열
var eee = doubleArrayOf(10.0,20.5,30.4) //Int 전용 배열
//StringArrayOf()는 없음 , 기본형만 존재!!
//빈 배열 5개 짜리 만들고 값은 나중에 넣는 형태
var fff = arrayOf<Int>() // 0개 짜리 배열임
var ggg = intArrayOf(0,0,0,0,0)
//위 말고 배열의 요소값의 시작을 그냥 null 값으로 주며 개수 지정
var hhh = arrayOfNulls<Double>(5)
for (t in hhh) println(t)
//즉 배열은 요소의 개수변경이 불가하단 특징을 가지고 있다
}
컬렉션 - List, Set, Map 특성의 대량의 데이터들
1) List : 요소가 순서대로 저장, 인덱스번호 자동부여, 중복 가능
2) Set : 순서 x , 인덱스 x, 중복 x
3) Map : Key - value 쌍, 순서 x , 인덱스 대신 key, key는 중복 x , value 중복 o
ex) API 파싱하거나 할 때 주로 쓴다
package com.bsj0420.ex01kotlinhello
fun main(){
//코틀린의 컬렉션은 모두 요소의 추가나 삭제 및 변경이 불가한 종류와 가능한 종류로 나뉨
//7-1) 요소개수 추가 삭제 및 변경 불가능한 컬렉션 : listOf(), setOf(), mapOf()
// List
val list: List<Int> = listOf(10,20,30,20)
for(i in list) println(i)
println()
//값의 추기/ 삭제/ 변경 관련된 어떤 기능 메소드도 없음
//list.add()
//list.set()
//list.remove()
// Set
val set:Set<Double> = setOf(3.14,5.55,12.7, 5.55) //중복 데이터 무시
for (e in set) println(e)
println()
// Map
// 1. Pair() 객체를 이용하여 만들기
val map:Map<String,String> = mapOf( Pair("title","Hello"), Pair("msg", "Hi") )
println("요소의 개수 : ${map.size}")
for( (key,value) in map ){
println("$key : $value")
}
println()
// 2. to연산자 사용하여 만들기
val map2: Map<String,String> = mapOf("id" to "mrhi12" , "pwd" to "123123")
for ( (k,v) in map2 ) println("${k} : ${v}")
println()
package com.bsj0420.ex01kotlinhello
fun main(){
//7-2) 요소개수 추가 삭제 및 변경 가능한 컬렉션 : mutableListOf(), mutableSetOf(), mutableMapOf()***
// mutableListOf()
val aaaa:MutableList<Int> = mutableListOf(1000,2000,3000)
println("요소 개수 : ${aaaa.size}")
aaaa.add(40000)
aaaa.add(0, 50000) //위치 명시
println("요소 개수 : ${aaaa.size}")
println()
//aaaa.set(1, 600)
aaaa[1] = 600 //마치 배열처럼 요소값에 접근하는 것을 권장함
for(i in aaaa) println(i)
println()
println("2번 방의 값 : ${aaaa.get(2)}")
println("2번 방의 값 : ${aaaa[2]}") //더 권장
println()
// mutableSetOf()
val bbbb:MutableSet<Double> = mutableSetOf()
println("요소 개수 : ${bbbb.size}") //0
bbbb.add(5.55)
bbbb.add(2.18)
bbbb.add(2.18) //무시
bbbb.add(9.7)
println("요소 개수 : ${bbbb.size}") //3
for (e in bbbb) println(e)
println()
// mutableMapOf()
val cccc:MutableMap<String, String> = mutableMapOf("name" to "sam", Pair("tell" , "010-1234-1234"))
println("요소 개수 : ${cccc.size}") //2
cccc.put("addr", "seoul")
println("요소 개수 : ${cccc.size}") //3
println()
for ((k,v) in cccc) println("$k : $v")
println()
//7-3) 별외 mutable 에 익숙하지 않다면
//자바의 ArratList, HashSet, HashMap 에 대응하는 클래스들이 있다
var arrayList: ArrayList<Any> = arrayListOf("aaa", 10, 45.87f)
//사용법은 mutable과 같다
var hashSet: HashSet<Any> = hashSetOf(100, "Good")
var hashMap: HashMap<String,Any> = hashMapOf("aaa" to 65)
}