Why do I get null?

54 Views Asked by At

My console says

Math: 5.0
false

English: 3.0
true

Physics: null
false

Chemistry: null
false

This sound ok, but in my Code I had a Exception-Code. I do not understand why I get null here:

Physics: null
Chemistry: null
class Course(
    val name: String
){
    var grade: Double? = null
        set(value){
            try {
                if (value != null && value >= 1.0 && value <= 6.0){
                    field = value
                }

            } catch ( e: NullPointerException ){
                field = 6.0
            }
        }

    var passed: Boolean? = null
        get(){
            return (this.grade ?:6.0) <= 4.0
        }

}

fun main(){
    val math = Course (" MATH ")
    math.grade = 5.0 //valid

    val english = Course (" ENGLISH ")
    english.grade = 3.0 // valid

    val physics = Course (" PHYSICS ")
    physics.grade = 0.7 // invalide

    val chemistry = Course (" CHEMISTRY ")
    chemistry.grade = 6.3 // invalide

    println("Math: " + math.grade )
    println( math.passed )
    println()

    println("English: " + english.grade )
    println( english.passed )
    println()

    println("Physics: " + physics.grade )
    println( physics.passed )
    println()

    println("Chemistry: " + chemistry.grade )
    println( chemistry.passed )
    println()

}

I want to get here

try {
    if (value != null && value >= 1.0 && value <= 6.0) {
        field = value
    }
} catch (e: NullPointerException ) {
    field = 6.0
}

for field 6.0, but not "null" how can I fix this Problem?

1

There are 1 best solutions below

0
cactustictacs On

Here's your variable and its setter function:

var grade: Double? = null
    set(value) {
        if (value != null && value >= 1.0 && value <= 6.0) {
            field = value
        }
    }

I removed the try/catch because it doesn't actually do anything - we'll get to that in a minute! So what you're left with is a setter that only updates if value is between 1.0 and 6.0. If it's outside that range, or null, the if condition fails and field (the actual stored value for the variable) isn't changed. And because its initial value is null, that's why you're still getting null when you print its value.


You should probably read up on exceptions and what the try/catch blocks actually do - here's the Java tutorial about it (the Kotlin docs assume you know this, and really just talk about how Kotlin approaches it).

But basically - if you try to call a function with a parameter that isn't supposed to be null, or you try to call a method or access a property on an object that's actually null, that will create an error called an Exception - something has gone wrong, and your code can't handle it. This exception will bubble back up through the call chain, and eventually crash your program, unless something in that chain catches it and handles it.

So by wrapping code in a try block, you're recognising that there's a possibility of an exception happening, and in the catch block you handle them (or certain types of exception, like a NullPointerException). And that's where you have your fallback behaviour, setting field to 6.0.

The problem is the code in your try block won't throw an NPE - there's nothing happening in there that's dangerous, you're even explicitly handling the possibility of null! (Which Kotlin forces you to do anyway, to avoid NPEs - it's designed around null-safety.)


The other issue is this - what exactly are you trying to do with the catch block? It's a fallback value, right? But you're only attempting to handle nulls anyway - what about the other cases, where value isn't null, but it's outside the valid range? Even if the try/catch trick did work, it wouldn't handle the case you're testing, which is setting an out-of-range value.

So really, you should be doing something like a simple if/else:

    set(value) {
        if (value != null && value >= 1.0 && value <= 6.0) {
            field = value
        } else {
            field = 6.0
        }
    }

There you go! Your if condition already defines the valid values, so you just need to add an else block that covers everything else. There are some other ways to express this too, but this is the simplest, and most important to understand.