作为kotlin的一个新开发人员,我第一次遇到了一个我很乐意得到解释的情况。方法findviewbyid的视图可以返回null(这是我作为java开发人员所知道的,但我很高兴知道,如果我能理解一个null值只能根据方法签名返回,而不需要打开android文档),但是我很惊讶编译器没有阻止我将返回值赋给一个非-可为空的视图对象。它不应该阻止这个任务吗?asaik,以下赋值将不编译:
var str1 : String? = "just a string"
var str2: String = str1
那么有什么区别呢?
2条答案
按热度按时间2wnc66cl1#
在kotlin中,如果没有null检查,就不能将可为null的值放入不可为null的变量中。
这将编译
b1payxdu2#
Kotlin的无效性检查是Kotlin公司捏造的。一旦一个类文件被生成,那个问号(或缺少问号)就消失了。编译器没有线索。是的,方法签名包含此信息(如果您的文件中包含:
fun helloWorld(): String { return "Hello" }
,并编译它,然后编写调用helloWorld()
,该代码知道helloworld函数已声明为返回一个非空字符串(即使您没有源文件),但也就是说,对于vm可执行文件java而言,是一个注解。这样,它与泛型完全相同。您可以这样做:
该代码将在最后一行抛出classcastexception,这很有趣,因为该行没有强制转换。你应该预料到
raw.add(5)
行抛出一些东西,但这不会,因为泛型是javac的虚构。如果javac在编译时没有阻止您,那么java虚拟机肯定也不会这样做。对于那些空类型也是如此。它不是空支票。
然而,请注意,kotlin可能会使用nullcheck注入显式代码,我不记得它是否为了java代码的利益而这样做。i、 e.本kotlin规范:
获取到伪代码的转换:
快速
javap
kotlinc吐出来的东西会告诉你它是否能做到这一点。这就导致了无效行为。
原来,有4种方法可以做泛型。要表示“数字列表”,有4种方法:
最后一个是棘手的:它允许一切,并有意(或多或少)让你打破东西。它不必存在,但它确实存在:在泛型存在之前就已经有了编写的代码,如果原始模式不可用,与遗留代码的交互将是非常痛苦的。
kotlin,以及所有各种基于注解的java空值系统(与kotlin做的一样好,工作原理完全相同),都需要处理这样一个事实,即95%的类文件形式的社区代码不包含任何空值提示。因此,需要将其视为“遗产”。
kotlin解决遗留问题的方式与java用泛型解决遗留问题的方式非常相似:什么都可以。
如果你给一个非空的东西赋一个旧的空值凯。Kotlin假设你知道自己在做什么。它可以注入一个显式的nullcheck,但是在任何地方都会有大量的nullcheck,如此之多,这将对类大小和性能产生显著的影响。在旧null参数的位置传递null?'凯。显然那没关系,Kotlin不知道,遵从你的代码。
顺便说一句,事实上,即使没有遗产有3个无效,而不是2应该告诉你,Kotlin的“要么事情是无效的或他们不是”是过于简单化,意味着Kotlin是不完整的前面。所以它是这样的:不可能编写一个方法来接受一个列表??空字符串并以任何方式适当地操作(因此您可以传入一个可空字符串或不可空字符串的列表,您的方法并不关心,同时您仍然可以同时获取(可空)字符串并添加xs,其中x是已知的非空字符串,或者(可能)从该列表中获取的空字符串。不变、协变和逆变的概念往往适用于所有类型关系和标记,空值是一个标记,就像“此列表包含字符串”是一个标记一样。