1

I am reading through the existing codebase for my team, and I notice mutableListOf are always declared as val. In some scenarios, elements are added to the mutableListOf only once. E.g

val jobList = mutableListOf<JobActivity>()
jobList.addAll(job.activities)

In other scenarios, elements are added to mutableListOf in a loop. E.g

val jobList = mutableListOf<JobActivity>()
newJobList.filterScanType(retrieveJobType(JobContext.NEW)).forEach {
    jobList.add(it)
}

Since the list is not initialized on creation, why not declare mutableListOf as var? A lot of examples found online also follow the same pattern of declaring mutableListOf as val.

Which is best to use in the 2 scenarios described, val or var?

Taseer
  • 3,432
  • 3
  • 16
  • 35
GraSim
  • 3,830
  • 1
  • 29
  • 35
  • 2
    If you are not referencing the `jobList` to a new instance of a mutable list, then go with `val`. That list is an object and the objects declared in `val` can have their properties changed even at run time. – Taseer Jun 20 '19 at 15:57
  • @TaseerAhmad Sorry don't understand answer. Can you expand with example? – GraSim Jun 20 '19 at 15:59
  • 3
    Always use `val` when you don't need it to be `var`. – EpicPandaForce Jun 20 '19 at 16:01
  • @EpicPandaForce Why? Are there performance or memory implications? Is it more expensive to use a var here? – GraSim Jun 20 '19 at 16:02
  • 2
    Same reason why you should make a `String` be `String` instead of `String?` if you don't actually expect it to be nullable. – EpicPandaForce Jun 20 '19 at 16:07
  • @GraSim I would suggest removing the Android tag, because it is not Android-related, but purely Kotlin. – Willi Mentzel Jun 20 '19 at 19:20
  • Have you understood the answer? If not I can provide a visual representation. – Taseer Jul 07 '19 at 14:08

6 Answers6

6

I think it's declared as val because the list will be the same always, the only thing that changes is it's elements. You'll never do something like:

joblist = anotherList

And as @Taseer said, the properties of the object can be changed even if it's a val. For example:

data class Example(var name: String)

val exampleObject = Example("SomeName")

You'll still be able to do this:

exampleObject.name = "AnotherName"

But you can't do this:

exampleObject = anotherObject
4

The general rule of thumb while using Kotlin.

Difference in val and var

You may already know the differences but for the sake of an answer, I will repeat it. var lets you modify the reference of an object while val does not permit to change the reference of an object.

An object can be declared safely using either var or val keyword but the reason why you want to use val on an object(in most cases) is that you don't want to refer that class member with a new reference of a new instance of an object. That way, you always keep a reference to the original object and you can modify object properties.

In the case of var, though nothing wrong with it, you can still use it 'without' any problems. You can still access the object properties and modify them and also you will be able to refer that class member to a reference of a new object.

Example:

val myObject = MyObject()
myObject.something = 1 //can still modify object property.
myOjbect = MyObject() //re-referencing the object, NOT POSSIBLE


var myNewObject = MyNewObject()
myNewObject.someThing = "Hello world!" //can still modify object properties
myNewObject = MyNewObject()  //can still reference it.

Why to use val over var in case of 'immutable' objects?

It gives you the security of not 'accidentally' placing a new reference.

But is there any performance benefit using val?

Answer: Final keyword benefit

Taseer
  • 3,432
  • 3
  • 16
  • 35
  • Did you mean to say : Why to use val over var in case of 'mutable' objects? – GraSim Jun 21 '19 at 11:15
  • No, I meant that `var` should be used with 'mutable' objects. Now what I mean by mutable objects is that those objects that you **reinitialize** and **reassign** to the already initialized object's variable. `val` on another hand should be used when you are not going to be **reassigning** or **reinitializing** the object with a new instance. Please read `Kotlin` basic syntax: [Basic Syntax](https://kotlinlang.org/docs/reference/basic-syntax.html), – Taseer Jun 21 '19 at 11:59
  • Yes var is used for mutable objects while "val" is used for "immutable" objects. Which is why I was wondering why you wrote "Why to use val over var in case of 'immutable' objects?" ...is that a question or a statement? Val is used for "immutable" objects. – GraSim Jun 22 '19 at 16:58
  • That is just a statement. I was trying to describe why to use `val` over `var` in case of 'immutable' objects. Not that why you should use `val` over `var` for no reason. It depends on your use case. – Taseer Jun 22 '19 at 17:02
2

val is more idiomatic for the reasons given in other answers and comments.

You said the val is not instantiated, but in your example code, it is.

val jobList = mutableListOf<JobActivity>()

is a factory that instantiates an empty MutableList<JobActivity>

Using this pattern (val not var, instantiated upon declaration) ensures that your code will never find an uninitialized or null value for jobList; and the compiler can prove it.

npskirk
  • 1,188
  • 1
  • 8
  • 21
1

In short - there are no rules, its up to you

if you use val you can modify mutableList, but not reassign

if you need reassign another list to same variable, use var. In most cases you dont need it, thats why your team uses it frequently

Andrey Danilov
  • 6,194
  • 5
  • 32
  • 56
1

Whether a variable is var or val distinguishes between a variable of which the value (reference) can be changed (var = mutable) or not (val = immutable).

You should always strive to use val over var to avoid unwanted side-effects (changing it in another thread for example).

In case of the MutableList you should most likely use a val, because you don't want to mutate the reference to the list but rather its contents.

Here an overview of your options:

// Do you want to change its reference (r) / contents (c)?
var a = mutableListOf(1, 2, 3) // r = yes, c = yes
var b = listOf(1, 2, 3)        // r = yes, c = no
val c = mutableListOf(1, 2, 3) // r = no,  c = yes
val d = listOf(1, 2, 3)        // r = no,  c = no
Willi Mentzel
  • 27,862
  • 20
  • 113
  • 121
0

You create a variable with var that is mutable (that can change). Mutable means variable can be changed in future.

val is used when variable will not be changed in future that means constant or final.

Here changed means new value or new things will be assigned to the variable but

val list = mutableListOf()

in this list variable you assigned mutable list. You just changed the value of the list. But you didn't assign new instance or new value to the variable you just added and remove value from the list. That's it. So here list is immutable itself.

It will be mutable if you do things like below...

var list = mutableListOf()
list = mutableListOf()

Two initialization on the same variable.

Shaon
  • 2,496
  • 26
  • 27