0

I am a beginner in kotlin and this is the code I tried to execute, but runtime error is being displayed. Please help me resolve this.

import java.util.*
fun main(args: Array<String>)
{
    var inp = Scanner(System.`in`);
    var t:Int = inp.nextInt();
    repeat(t)
    {
        var n:Int = inp.nextInt();
        var s:String = readLine()!!
        for (i in s)
        {
            println(i);
        }
        println()
        
    }
}

Exception in thread "main" kotlin.KotlinNullPointerException at ProgKt.main(prog.kt:10) This is the error that is displayed.

2 Answers 2

3

Smeki's answer is right, but I just need to point something out since you're a beginner and it might get confusing.

Normally you'd do something like this:

val s = readLine()

Notice you're not specifying the type of s - it's being inferred by whatever you're assigning to it. Because readLine returns a nullable String?, which is a String that could be null (which is what the ? on the end means), then the compiler knows that s is a String?. It's the equivalent of doing this:

val s: String? = readLine()

And you can do that explicitly if you want! You usually don't need to though. And now you have your nullable s, you can do some null-checking to use it safely:

if (s != null) {
    // we know it's not null, so now you can do stuff with it
} else {
    // if you like, you can handle the null case separately, like breaking out of 
    // the loop (since null from readLine() means you've reached the end)
}

There's other ways to handle nulls and do null-checking - here's the documentation about it and I'd strongly recommend reading it and getting your head around it - it's a key part of the language! And it makes your life easier and code safer in the long run (avoids problems like this! !! gets around null-safety and it's usually a bad sign)


But remember when I said you can explicitly declare the type for s? Here's what I said it would be, and what you've written:

// correct
val s: String? = readLine()
// something's different!
val s: String = readLine()

See how you're missing the ? that says its a nullable type? Even if you're planning to null-check s after this, it's going to crash at this line because s is declared as a non-null type, and readLine() is gonna to be null at some point. When you assign null to a non-null variable, it'll crash with an error - because as far as the compiler's concerned, something's gone wrong.

(You should also get some warnings in your IDE if you're using one, trying to null-check a variable that you've declared as non-null will give you some "why are you trying to do this? It can't be null, right?" messages that hint that something's wrong somewhere. Also if you didn't add the !! after readLine(), you'd get a warning about that - probably why you added the !! in the first place! It doesn't make the problem go away, just stops the IDE from warning you about it)


Also you might have noticed, I made s a val instead of a var because it's a fixed value you're not going to change - always prefer vals unless you definitely need to change that variable, it's not such a big deal here but it makes some other things easier (you'll get warnings about that too)

Sign up to request clarification or add additional context in comments.

3 Comments

Since this answer already goes quite in depth in explaining null safety, for completeness, I'd recommend to OP to also read the docs. Especially the part about the Elvis operator which might be usable in this scenario as well.
@cactustictacs Thank You for your well detailed explanation. Now I get it. I explicitly used var since, val is unmutable and can be quite difficult to use when trying to code for competitive programming and I might need to reassign a new string to the variable ;D
@AvinashDoddi you're not reassigning it though! You just create a new one every loop and it's initialised with the result of readLine and it never changes over its lifetime - it should be a val, that's the right tool for the job. vars are useful too, but if you use them for a value that doesn't change, your intent is less clear. And it can cause issues with smart casting and null-checking, because if you check a var isn't null, that value could be changed to null while you're using it (depending on the var's visibility). So the compiler can't make guarantees like it can with a val
1

Well, NPE is the most probably thrown from

var s:String = readLine()!!

where those !! are part of kotlin null-safety feature. And from java doc of readLine() we can find out when is null returned.

/**
 * Reads a line of input from the standard input stream.
 *
 * @return the line read or `null` if the input stream is redirected to a file and the end of file has been reached.
 */
fun readLine(): String? = LineReader.readLine(System.`in`, Charset.defaultCharset())

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.