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.
toString()that dumps all items respectively theirtoString()methods. You will have to iterate/stream the items of an array.