Ahmed Shaker
Ahmed Shaker

Reputation: 25

stackoverflowerror in Kotlin

I'm new to kotlin and I have a problem with code: I don't know why exactly when I create an instance of a class it gives me a stackoverflow error

Here is the code :

class Spice(val spiceName: String,val spiciness: String = "mild") {

    init {
        println("[$spiceName - $spiciness] ")
    }

    val spiceList: List<Spice> = listOf(
            Spice("curry", "mild"),
            Spice("pepper", "medium"),
            Spice("cayenne", "spicy"),
            Spice("ginger", "mild"),
            Spice("red curry", "medium"),
            Spice("green curry", "mild"),
            Spice("hot pepper", "extremely spicy"))

    val heat: Int
        get() {
            return when (spiciness) {
                "mild" -> 1
                "medium" -> 3
                "spicy" -> 5
                "very spicy" -> 7
                "extremely spicy" -> 10
                else -> 0
            }
        }


    fun makeSalt() = Spice("Salt")

}

Upvotes: 1

Views: 2313

Answers (3)

CodeRanger
CodeRanger

Reputation: 370

Here is your mistake:

val spiceList: List<Spice> = listOf(
Spice("curry", "mild"),
Spice("pepper", "medium"),
Spice("cayenne", "spicy"),
Spice("ginger", "mild"),
Spice("red curry", "medium"),
Spice("green curry", "mild"),
Spice("hot pepper", "extremely spicy"))

you are creating list of spices in each instance, and each Spice item in the list is creating list of spices and so on, then you will face a burst!. you could use a sealed class for this situation, or just use companion object to make it as a static list.

Upvotes: 0

Rafa
Rafa

Reputation: 3349

This is because You're creating a new instance of your Spice() class whenever you call

val spiceList: List<Spice> = listOf(
  Spice("curry", "mild"),
  Spice("pepper", "medium"),
  Spice("cayenne", "spicy"),
  Spice("ginger", "mild"),
  Spice("red curry", "medium"),
  Spice("green curry", "mild"),
  Spice("hot pepper", "extremely spicy"))

What's happening is that at runtime the first line that will execute is the init block so you'll print.

[Whatever you passed in for your first param, "mild"]

then when you you're past the init you move on to evaluating

val spiceList = listOf(....)

in Kotlin, assignments are resolved at runtime meaning, even though you're not using spiceList, you're still creating it at that line, along with all the other Spice() objects inside it.

You'll notice that before you get the stackoverflow, you actually print

[Whatever you passed in for your first param, "mild"]
["curry", "mild"] x thousands of times

Because you're instantiating Spices within Spices, you'll always be stuck in that loop.

You could move your list to a companion object, which would be treated like a static is in Java, and that way it won't be resolved whenever you instantiate the Spice class

Upvotes: 3

Kirill Simonov
Kirill Simonov

Reputation: 8481

It's because of spiceList field: every instance of Spice will try to initialize this field and hence create a list of Spices, each of which will create a new list and so on.

You could move spiceList to a companion object to make it tied to a class rather than to instances of it.

Upvotes: 6

Related Questions