본문 바로가기
언어/Kotlin&Java

[코틀린/Kotlin] 기초 #02_문자열( == vs ===)

by 옹구스투스 2021. 7. 28.
반응형

환경 : Kotlin Version = 1.5.20, JVM, Android Studio

 

코틀린의 문자열 사용법과, 유용한 기능에 대해 알아보자.

0.참고 자료

https://kotlinlang.org/docs/basic-types.html#strings

 

Basic types | Kotlin

 

kotlinlang.org

 


1. String

  • 여러 문자를 배열하여 저장할 수 있는 자료형이다.
  • 문자열의 인덱스를 통해 각각의 문자에 접근할 수 있다.
  • Char은 char과 같은 기본형으로 처리되지만 문자열 자료형은기본형에 속하지 않는 배열 형태로 되어있는
    특수한 자료형이다.
  • 문자열은 힙 메모리 영역의 String Pool이라고 부르는 공간에 문자열을 저장해두고 이 값을 변수에서 참조한다.
  • String 문자열은 참조 타입이므로, 문자열 뒤에 문자열을 추가하는 것 같은 수정 작업을 한다면,
    기존에 참조하고 있던 String Pool 영역에 저장된 문자열에 추가하는 것이 아니라, 추가된 문자열을 새로 String Pool에 생성(저장)하여 참조를 이곳으로 바꾸는 것이다.
    val str1 : String = "Hello"
    val str2 = "World"
    val str3 = "Hello"

    println(str1[1])
    //result : e
    for(c in str1){
        println(c)
    }
    //result :
    //H
    //e
    //l
    //l
    //o

    //str1과 str2는 모두 String Pool 에 생성(저장)된 Hello를 참조하는 변수이다.
    println(str1 === str3) //str1과 str2이 참조하는 주소가 같다
    //result : true
    println(str1 === str2) //str1과 str2이 참조하는 주소가 다르다
    //result : false
    println(str1 == str2) //str1과 str2의 값이 같다
    //result : true

2. == vs ===

위의 코드에서 ==연산과 ===연산을 사용했다. 이 둘의 차이는 뭘까?

 

우선 Java에서 ==는 원시 타입(기본타입)을 비교할 때, 참조 타입을 비교할 때 두 가지 경우로 나뉜다.

원시 타입을 비교할 때 ==는 두 피연산자의 값이 같은지 비교하는데,

이를 동등성(identity)이라고한다. (값이 같다)

ex) int a=1, int b=2; a==b //false

 

참조 타입을 비교할 때 ==는 두 피연산자의 주소값을 비교한다.

참조 타입에서 두 피연산자의 주소값이 같다는 것은 즉 두 개의 오브젝트가 완전히 동일한 것을 의미하며

이를 동일성(equality)이라고한다.

ex)

※아래는 예시일 뿐, 실제론 a와 b의 주소값이 같다.

String a="hi"; //주소값이 1번지 

String b="hi"; //주소값이 2번지

a==b //false

 

만약 Java에서 참조 타입을 비교할 때, 두 오브젝트의 동등성(값이 같은지)을 알기 위해선 equals함수를 사용한다.

ex) a.equals(b) //true

 

이제 Kotlin을 확인해보자. 

Kotlin에서도 원시 타입을 비교할 때는 ==연산자가 Java와 동일하게 동등성을 비교한다.

ex)

val a=10 

val b=20

val c=10

a==b //false

a==c //true

 

그러나 참조 타입을 비교할 때는 Java와 차이가 있다.

Kotlin에서 참조 타입을 비교할 때 ==는 내부적으로 Java의 equals함수를 호출한다.

즉, 참조타입의 ==도 동등성(값이 같은지)을 비교한다.

ex)

val a : String ="hi"

val b : String ="hi"

a==b //true

 

그렇다면 Kotlin에서 참조 타입의 동일성(주소값이 같은지)을 비교하려면 어떻게 해야 할까?

바로 ===를 사용하면 된다.

Kotlin의 ===는 Java의 참조타입의 동일성을 비교하는 ==와 동일하다.

ex)

val a : String ="hi"

val b : String ="hi"

a===b //true

이를 표로 정리하고 알아두자.

위에서 정리한 내용을 바탕으로 실제로 Kotlin에서 ==와 ===가 다르게 동작하는지 코드로 확인해보자.

    //문자열을 String Pool에 저장하지 않는 방식
    val str4 = String(StringBuilder("Hello"))
    val str5 = String(StringBuilder("Hello"))
    
    println(str4 == str5)
    //result : true
    println(str4 === str5)
    //result : false

//StringBuilder에 대한 설명은 추후에 업로드하겠다.


3. 문자열의 다양한 기능

다음으로 Kotlin 문자열의 다양한 기능과 사용법을 알아보자.

 

 1) String literals

  • 문자열에 이스케이프 문자를 포함할 수 있다.
  • """를 사용하면 개행이나 공백을 포함한 모든 문자열을 자유롭게 사용할 수 있다.// 이스케이프 문자를 사용하지
    않아도 된다.
    val str1 = "Hello, world!\n"
    println(str1)

    val text = """
i
    love
          you
    """
    println(text)

    // |(Shift + \)과 .trimMargin()을 사용하여 앞의 공백을 없앨 수도 있다.
    val text1 = """
    |Tell me and I forget.
    |Teach me and I remember.
    |Involve me and I learn.
    |(Benjamin Franklin)
    """.trimMargin()
    println(text1)

 

 2) 문자열 템플릿

    val a = 1
    val b = 2
    var str = "abc"

    println("str == $str, a+b == ${a+b}")
    println("$str.length is ${str.length}")

    var s1 = "a is $a"
    println(s1)
    var s2 = "${s1.replace("is","was")}, but now is $a"
    println(s2)

 

3) 문자열 사용법

    var str ="abc"

    println("str==$str")
    println("str[1]==${str[1]}")
    println("str.length == ${str.length}")
    str= str+'d'
    println("str+'d' == $str")
    println("str.substring(0,2) == ${str.substring(0,2)}") //0부터 2개를 리턴
    println("str.contains(\"ab\") == ${str.contains("ab")}")
    println("str.equals(\"abcd\") == ${str.equals("abcd")}") //==연산과 같다
    println("Character.isDigit(str[0]) == ${Character.isDigit(str[0])}") //정수인지 확인
    println("str[0].isUpperCase() == ${str[0].isUpperCase()}") //대문자인지 확인
    println("str[0].isLowerCase() == ${str[0].isLowerCase()}") //소문자인지 확인
    println("str[0].isLetter() == ${str[0].isLetter()}") //알파벳인지 확인
    println("str[0].isWhitespace() == ${str[0].isWhitespace()}") //공백인지 확인
    println()

    var str1 = "hello my name is stevie"
    println("str1== $str1")
    println("str1.replace == ${str1.replace(" ","")}")//공백 제거
    println("str1.replace == ${str1.replace("stevie","jackson")}")
    println("str1.indexOf(\"e\") == ${str1.indexOf('e')}") //'e'가 있는 맨 앞 인덱스를 리턴
    println("str1.toUpperCase() == ${str1.toUpperCase()}")
    println()

    var list = str1.split(" ") //공백을 기준으로 나누어 list에 List 형식으로 저장
    println("list의 타입은 : ${list.javaClass.name}")
    println("list[0] == ${list[0]}, list[2] == ${list[2]}")
    println("list.joinToString(\"-\") == ${list.joinToString("-")}")
    println()

    val str2 = "123"
    println("str2.toInt() + 100 == ${str2.toInt()+100}")

반응형

댓글