Search code examples
androidkotlinmutablelist

Variable is used by reference when added to Mutable List


I'm adding new items to mutable list by setting header and detail data in val production.

val productionList = mutableListOf<ProductionData>()
val production = ProductionData()

//Assign header data
production.dateHeader = headerData.date
production.timeHeader = headerData.time

//Iterate detail data
for (item in detailData) {
   //Assign detail data
    production.timeDetail = item.timeDetail

    //Add new product
    productionList.add(production)
}

The problem is that on second iteration, production.timeDetail is modified but the productionList[0] is also modified.

How can I add items by value and not by reference as it is now? What am I doing wrong?


Solution

  • There is no support for adding to a list by value in Kotlin. A List can only hold references to classes.

    Kotlin does have something called inline classes that can be passed by value under some circumstances, but they cannot be stored in Lists as values. Lists exclusively store references. The primitive classes (Byte, Char, Int, Long, Double, Float) are inline classes that have special array types (e.g. IntArray) that can hold actual values instead of references, but there is no way to do this for any other types of inline class. Notably, inline classes are all immutable, so you usually don't even have to think about whether they're being used as references versus as values except when you're optimizing code performance.

    The standard generic Array type can only hold references.

    You must manually copy objects into new instances if you want to modify what's in a list without modifying the original instance. If your class is a data class, it has a built-in copy() function for this purpose. See here for documentation about how this works.

    It is common for robustness reasons to make your data classes immutable, which means that all of their properties are val instead of var. Then you cannot accidentally mutate a reference.