我是kotlin的初学者,这是我试图执行的代码,但是运行时错误正在显示。请帮我解决这个问题。
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()
}
}
线程"main"异常芬兰湾的科特林。KotlinNullPointerExceptionProgKt.main (prog.kt: 10)这是显示的错误。
Smeki的答案是正确的,但是我需要指出一些事情,因为你是初学者,它可能会让你感到困惑。
通常你会这样做:
val s = readLine()
注意,您没有指定s
的类型-它是由您分配给它的任何内容推断出来的。因为readLine
返回一个可空的String?
,这是一个String
,可以为空(这是?
在最后的意思),然后编译器知道s
是一个String?
。这相当于这样做:
val s: String? = readLine()
如果你愿意,你可以显式地这样做!不过你通常不需要这么做。现在你有了可空的s
,你可以做一些空检查来安全地使用它:
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)
}
还有其他方法可以处理空值并进行空值检查-这里是关于它的文档,我将强烈建议你阅读它,并了解它——它是语言的关键部分!从长远来看,它使您的生活更轻松,代码更安全(避免了这样的问题!!!
绕过null安全,这通常是一个坏信号)
还记得我说过可以显式声明s
的类型吗?以下是我说的内容,以及你写的内容:
// correct
val s: String? = readLine()
// something's different!
val s: String = readLine()
看到你怎么错过了?
,说它是一个可空类型?即使您计划在此之后对s
进行空检查,它也会在这行处崩溃因为s
被声明为非空类型,并且readLine()
在某些时候将为null。当你将null赋值给非null变量时,它会崩溃并报错——因为就编译器而言,有些地方出了问题。
(你也应该得到一些警告在你的IDE中,如果你使用一个,尝试null检查一个变量,你已经声明为非空会给你一些"为什么你试图这样做?它不可能是空的,对吧?暗示某个地方出了问题的信息。此外,如果您没有在readLine()
之后添加!!
,则会收到有关此的警告-这可能是您首先添加!!
的原因!它不会使问题消失,只是阻止IDE警告您)
你也可能已经注意到,我把s
改成了val
而不是var
,因为它是一个固定的值,你不会改变-总是喜欢val
s,除非你确实需要改变这个变量,这不是什么大问题,但它使其他一些事情更容易(你也会得到警告)
NPE最有可能是从
抛出的var s:String = readLine()!!
where those !!是kotlin零安全功能的一部分。从readLine()的java文档中我们可以知道什么时候返回null。
/**
* 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())