Home > Mobile >  Kotlin ArrayList and arrayOf have different behaviour for toString() method
Kotlin ArrayList and arrayOf have different behaviour for toString() method

Time:08-09

Why would the Use case 1 (arrayOf) print the cryptic object address while ArrayList correctly understands and print the object properties. It is odd because, not just ArrayList, but setOf, listOf etc. all print the object properties correctly. It's seems arrayOf is somehow different.

data class Student(
    val id: String,
    val name: String
)

fun main() {
    val hello1 = Student("1", "A")
    val hello2 = Student("2", "B")

    // USE CASE 1
    val arr = arrayOf(hello1, hello2)
    println(arr)
        
    // OUTPUT: [LStudent;@37f8bb67

    //USE CASE 2
    val arr2 = ArrayList<Student>()
    arr2.add(hello1)
    arr2.add(hello2)
    println(arr2)
        
    // OUTPUT: [Student(id=1, name=A), Student(id=2, name=B)]    

}

CodePudding user response:

Yes, arrayOf is somehow different… It's (like in) Java, it does not have a toString() method, but in Kotlin, it has a joinToString(…) which you can easily use in order to mimic the built-in toString() of Java/Kotlin collections:

fun main(args: Array<String>) {
    // prepare an array
    val hello1 = Student("1", "A")
    val hello2 = Student("2", "B")
    val arr = arrayOf(hello1, hello2)
    // join its items to a String with separator, prefix and postfix
    val joinedToString = arr.joinToString(", ", "[", "]")
    // and print it
    println(joinedToString)
}

Result:

[Student(id=1, name=A), Student(id=2, name=B)]

As mentioned (and answered) by @Joeffrey, you can do that with less code since there's Array.contentToString():

The very same output as above can be achieved through

fun main(args: Array<String>) {
    // prepare an array
    val hello1 = Student("1", "A")
    val hello2 = Student("2", "B")
    val arr = arrayOf(hello1, hello2)
    // and print it using a specific (new?) method for it
    println(arr.contentToString())
}

CodePudding user response:

It is odd because, not just ArrayList, but setOf, listOf etc. all print the object properties correctly. It's seems arrayOf is somehow different.

Yes it is different, and maybe it's more different than you thought. I'm not exactly sure where the confusion occur so let me clarify some things.

To start with, arrayOf doesn't give you an ArrayList, it returns an Array, which is a different type. So there is no real reason to expect their toString to behave similarly. You might be confusing arrayOf with arrayListOf, which would indeed give you an ArrayList.

An ArrayList is a subtype of List, which is itself a subtype of Collection. ArrayList just happens to be a collection that is backed by an array (hence the name), but it doesn't make it an array itself. Also, there are many other types of lists.

The other builders you mention here (and that behave as you expect) return Collection subtypes:

  • listOf() may return any subtype of List (including ArrayList)
  • setOf() may return any subtype of Set

Collections have a nice toString() implementation that prints their elements. Arrays don't have a specific toString() method implementation, and only have the default one (this is legacy from Java), hence the type and memory address in the output.

However, you can use the contentToString extension on arrays to have a similar result as collections' toString() output:

val hello1 = Student("1", "A")
val hello2 = Student("2", "B")

val arr = arrayOf(hello1, hello2)
println(arr) // prints: [LStudent;@37f8bb67
println(arr.contentToString()) // prints: [Student(id=1, name=A), Student(id=2, name=B)]

val list = arrayListOf(hello1, hello2)
println(list) // prints: [Student(id=1, name=A), Student(id=2, name=B)]

Note that you shouldn't really use arrays in business code in Kotlin, as most stdlib APIs revolve around List and other collections. Arrays should probably be considered more low-level primitives in Kotlin.

  • Related