1

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)]    

}
1
  • 3
    An array is not a list and in Java (at least), an array does not have a toString() that dumps all items respectively their toString() methods. You will have to iterate/stream the items of an array. Commented Aug 8, 2022 at 13:41

2 Answers 2

3

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.

Sign up to request clarification or add additional context in comments.

2 Comments

May be worth stressing (since I can't see it stated explicitly, and suspect it's a source of confusion) that ArrayList is a type of List; it is not an array (though it happens to use one internally). Similarly, LinkedList is a type of List that uses a series of linked nodes internally. The different List implementations vary in things like performance (memory, CPU), mutability, support for null values or random access — as indicated by their name and hence implementation — but as far as the language is concerned they're all just List (and often MutableList) implementations.
Thanks for the feedback. Indeed given the name arr2 for the second variable in the question, there may be a confusion with what an ArrayList is. I updated the answer
1

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())
}

12 Comments

No need for joinToString here, it's already built-in with Array.contentToString()
I think it's because it's an extension on arrays, defined in the collections package. So it doesn't appear as array methods. You can see the link to the doc of this method in my answer
That seems to be the (small) downside of the (great) idea of extension functions ;-) The docs get harder to read ;-)
@deHaar If you're using a decent IDEA (IntelliJ being the most common), then you don't usually need to look at the docs — just type myArray. and see what pops up!
@deHaar AIUI, support for autocompletion in IDEs is one of the main benefits of extension functions over stand-alone static utility functions (which is what you have to do in Java, and how extension functions are actually implemented in Kotlin/JVM…)
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.