Kotlin массив не сохраняет значение после запуска - PullRequest
0 голосов
/ 27 мая 2020

Столкнулся с неожиданной проблемой. Вот простой класс:

class PaymentPrintTest {

    init {
        prepareToPrint()
    }

    private var sale: Int? = null
    private var saleContent: ArrayList<Int> = ArrayList()

    private fun prepareToPrint() {

        sale = 5
        saleContent = arrayListOf(1,2,3)

        Log.i("WhereIsContent?", "prepare sale: $sale")
        Log.i("WhereIsContent?", "prepare saleContent: ${saleContent.size}")
    }

    fun startPrint() {

        Log.i("WhereIsContent?", "start sale: $sale")
        Log.i("WhereIsContent?", "start saleContent: ${saleContent.size}")

    }

}

Таким образом я вызываю метод startPrint:

PaymentPrintTest().startPrint()

В logcat я вижу:

I/WhereIsContent?: prepare sale: 5
I/WhereIsContent?: prepare saleContent: 3

I/WhereIsContent?: start sale: 5
I/WhereIsContent?: start saleContent: 0

Вопрос в том, Куда делось содержание saleContent? И почему переменная sale при этом имеет правильное значение?

Ответы [ 4 ]

3 голосов
/ 27 мая 2020

Переместить продажи и распродажу Содержимое выше init, свойства должны быть на самом верху

0 голосов
/ 28 мая 2020

Я знаю, что приведенные выше ответы дают правильный результат. Но я просто хочу дать небольшое объяснение.

1) давайте начнем с

var sale: Int? = null

если блок инициализации предшествует объявлению свойств, блок инициализации просто принимает имена своих свойств, а не присвоенные им значения (даже если бы это было var sale: Int? = 4, он бы проигнорировал 4) . Он присваивает им значения по умолчанию, в вашем случае null, , но этот null НЕ тот, который вы назначили, это значение по умолчанию для свойства, допускающего значение null. Таким образом, если это была var sale: Int = 4, значение продажи в блоке init было бы 0 (значение по умолчанию Int). Затем вы присвоили 5 продаже . После завершения блока инициализации проверяется свойство sale . Если этому свойству было присвоено значение по умолчанию (в вашем случае null), оно просто игнорирует присвоение (оставляя его текущее значение, равное 5), в противном случае оно снова переназначает свойство (так, если бы это было var sale: Int? = 4, он снова переназначит его на 4)

Но, если инициализация происходит после объявления свойства, все должно быть ясно и, как ожидалось;).

2) давайте обратимся к

private var saleContent: ArrayList = ArrayList ()

в этом случае берется имя свойства saleContent (не ArrayList ()), и поскольку для этого нет значения по умолчанию, ему ничего не присваивается. Внутри блока инициализации вы назначили (1, 2, 3), который изменил свое значение с не назначенного на (1,2,3). Но когда блок инициализации завершился, он был переназначен на (ArrayList ()), потому что ArrayList () не является значением по умолчанию для ArrayList.

но если поместить свойства выше init, он работает как обычно.

    private var sale1: Int? = null
    private var sale2: Int? = 3
    private var sale3: Int = 0
    private var sale4: Int = 9
    private var saleContent: ArrayList<Int>? = null
    lateinit var saleContent2: ArrayList<Int>

если вы поиграете с этими значениями, я надеюсь, вы поймете больше.

Но как правило, я бы посоветовал поместить блок инициализации после объявления свойства, чтобы быть в безопасности.

0 голосов
/ 27 мая 2020

Вы можете сделать saleContent a lateinit var, но для этого вам нужно удалить прямую инициализацию. См. Этот пример:

class PaymentPrintTest {

    init {
        prepareToPrint()
    }

    private var sale: Int? = null
    private lateinit var saleContent: ArrayList<Int>

    private fun prepareToPrint() {
        this.sale = 5
        this.saleContent = arrayListOf(1,2,3)

        println("WhereIsContent?\tprepare sale: $sale")
        println("WhereIsContent?\tprepare saleContent: ${saleContent.size}")
    }

    fun startPrint() {
        println("WhereIsContent?\tstart sale: $sale")
        println("WhereIsContent?\tstart saleContent: ${saleContent.size}")
    }
}

Мне пришлось использовать println() вместо Log, потому что я написал это в Kotlin Playground без LogCat ...

Однако результат

fun main() {
    PaymentPrintTest().startPrint()
}

равен

WhereIsContent? prepare sale: 5
WhereIsContent? prepare saleContent: 3
WhereIsContent? start sale: 5
WhereIsContent? start saleContent: 3

Очевидно, это работает так, но также работает так, как ответил @Jaime.

0 голосов
/ 27 мая 2020

Когда вы инициализируете arraylist глобально, для обоих методов будет использоваться глобальный Arraylist.

Если вы измените его таким образом, он будет работать так, как вы хотите.

    class PaymentPrintTest {

    init {
        prepareToPrint()
    }

    private var sale: Int? = null
    private var saleContent: ArrayList<Int>? = null

    private fun prepareToPrint() {

        sale = 5
        saleContent = arrayListOf(1,2,3)

        Log.i("WhereIsContent?", "prepare sale: $sale")
        Log.i("WhereIsContent?", "prepare saleContent: ${saleContent?.size}")
    }

    fun startPrint() {

        Log.i("WhereIsContent?", "start sale: $sale")
        Log.i("WhereIsContent?", "start saleContent: ${saleContent?.size}")

    }
}

вывод:

> I/WhereIsContent?: prepare sale: 5
I/WhereIsContent?: prepare saleContent: 3
I/WhereIsContent?: start sale: 5
I/WhereIsContent?: start saleContent: 3
...