在java中可以为null的返回值是否可以放在kotlin中声明为非null的变量中



作为Kotlin的一名新开发人员,我第一次遇到这样的情况,我很乐意得到解释。View的methodfindViewById可以返回null(作为java开发人员,我知道这一点,但我很高兴知道我是否能理解,只有根据方法签名才能返回null值,而无需打开android文档(但是我很惊讶编译器没有阻止我将返回值分配给不可为null的View对象。难道它不应该阻止这项任务吗?ASAIK,以下任务不会编译:

var str1 : String? = "just a string"
var str2: String = str1

那么有什么区别呢?

Kotlin的无效性检查是Kotlin的虚构。一旦生成了一个类文件,那个问号(或没有问号(就消失了。编译器没有任何线索。是的,方法签名有这样的信息(如果你有一个文件,其中包含:fun helloWorld(): String { return "Hello" },并对其进行编译,然后编写其他调用helloWorld()的代码,则该代码知道helloworld函数已被声明为返回非空字符串,即使你没有源文件(-但就java而言,VM可执行文件是一个注释。

通过这种方式,它与泛型完全相同。你可以这样做:

public void iWillMessYouUp(List<String> list) {
List raw = list; // this generates a warning, but compiles.
raw.add(5); // this compiles. I just added an Integer to a String list...
}
List<String> myList = new ArrayList<String>();
iWillMessYouUp(myList);
for (Integer i : myList) System.out.println(i);

该代码将在最后一行抛出ClassCastException,这很有趣,因为这一行没有强制转换。您可能期望raw.add(5)行抛出一些东西,但不会,因为泛型是javac的一个组成部分。如果javac在编译时没有阻止您,那么javathevm当然也不会这么做。

那些null类型也是如此。它不是一个null检查。

然而,请注意,kotlin可能会注入带有null检查的显式代码,我不记得它是否是为了例如java代码的利益而这样做的。即此kotlin代码:

fun say(in: String) {
println(in)
}

获得翻译为伪代码:

METHOD say(Ljava/lang/String;)V {
if (in == null) throw new NullPointerException("in");
java.lang.System.out.println(in);
}

一个关于kotlinc吐出什么的快速javap会告诉你它是否会这样做。

这使我们的行为无效。

事实证明,有4种方法可以实现泛型。要表示"数字列表",有4种方法:

List<Number> // invariant
List<? extends Number> // covariant
List<? super Number> // contravariant
List // raw

最后一个很棘手:它允许一切,并有意(或多或少(让你打碎东西。它不必存在,除非它真的存在:在泛型存在之前就已经有了代码,如果原始模式不可用,那么与遗留代码的交互将非常痛苦。

Kotlin,以及所有用于java的基于注释的无效性系统(它们和Kotlin一样好,实际上原理相同(,需要处理这样一个事实,即95%的类文件形式的社区代码都不包含任何关于无效性的提示。因此,它需要被视为"遗产"。

kotlin解决遗留问题的方式与java用泛型解决遗留问题非常相似:任何事情都可以

如果你给一个非null的东西分配一个legacy null的值?"凯。Kotlin假设你知道自己在做什么。它可以注入一个显式的null检查,但这将是到处都是null检查的LOT,数量如此之多,这将对类大小和性能产生显著影响。在旧的null参数的位置传递null?'凯。显然,那没关系,kotlin不知道,并服从你的代码。

顺便说一句,即使没有遗产,也有3个无效,而不是2个无效,这一事实应该告诉你,kotlin的";要么事物是可以为null的,要么它们不是"null";过于简单化,意味着科特林在这方面是不完整的。事实是这样的:不可能写一个方法来接受??的列表??nullity字符串,并以任何一种方式适当地执行(因此,您可以传入一个可为null的字符串或不可为null字符串的列表,您的方法不在乎,同时您仍然可以取出(可为null(字符串,并添加X,其中X是已知的非null字符串,或者是您从该列表中获得的(可能(null字符串。不变量、协变和反变的概念往往适用于所有类型关系和标记,零是一个标记,就像"此列表包含字符串"是一个一样。

在kotlin中,如果不进行null检查,就不能将可为null的值放入不可为null变量中。

这将编译

var str1 : String? = "just a string"
if(str1!=null){
var str2: String = str1
}

最新更新