可以将java中可以为null的返回值放入kotlin中声明为非null的变量中吗

aelbi1ox  于 2021-07-08  发布在  Java
关注(0)|答案(2)|浏览(327)

作为kotlin的一个新开发人员,我第一次遇到了一个我很乐意得到解释的情况。方法findviewbyid的视图可以返回null(这是我作为java开发人员所知道的,但我很高兴知道,如果我能理解一个null值只能根据方法签名返回,而不需要打开android文档),但是我很惊讶编译器没有阻止我将返回值赋给一个非-可为空的视图对象。它不应该阻止这个任务吗?asaik,以下赋值将不编译:

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

那么有什么区别呢?

2wnc66cl

2wnc66cl1#

在kotlin中,如果没有null检查,就不能将可为null的值放入不可为null的变量中。
这将编译

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

b1payxdu2#

Kotlin的无效性检查是Kotlin公司捏造的。一旦一个类文件被生成,那个问号(或缺少问号)就消失了。编译器没有线索。是的,方法签名包含此信息(如果您的文件中包含: fun helloWorld(): String { return "Hello" } ,并编译它,然后编写调用 helloWorld() ,该代码知道helloworld函数已声明为返回一个非空字符串(即使您没有源文件),但也就是说,对于vm可执行文件java而言,是一个注解。
这样,它与泛型完全相同。您可以这样做:

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在编译时没有阻止您,那么java虚拟机肯定也不会这样做。
对于那些空类型也是如此。它不是空支票。
然而,请注意,kotlin可能会使用nullcheck注入显式代码,我不记得它是否为了java代码的利益而这样做。i、 e.本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);
}

快速 javap kotlinc吐出来的东西会告诉你它是否能做到这一点。
这就导致了无效行为。
原来,有4种方法可以做泛型。要表示“数字列表”,有4种方法:

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

最后一个是棘手的:它允许一切,并有意(或多或少)让你打破东西。它不必存在,但它确实存在:在泛型存在之前就已经有了编写的代码,如果原始模式不可用,与遗留代码的交互将是非常痛苦的。
kotlin,以及所有各种基于注解的java空值系统(与kotlin做的一样好,工作原理完全相同),都需要处理这样一个事实,即95%的类文件形式的社区代码不包含任何空值提示。因此,需要将其视为“遗产”。
kotlin解决遗留问题的方式与java用泛型解决遗留问题的方式非常相似:什么都可以。
如果你给一个非空的东西赋一个旧的空值凯。Kotlin假设你知道自己在做什么。它可以注入一个显式的nullcheck,但是在任何地方都会有大量的nullcheck,如此之多,这将对类大小和性能产生显著的影响。在旧null参数的位置传递null?'凯。显然那没关系,Kotlin不知道,遵从你的代码。
顺便说一句,事实上,即使没有遗产有3个无效,而不是2应该告诉你,Kotlin的“要么事情是无效的或他们不是”是过于简单化,意味着Kotlin是不完整的前面。所以它是这样的:不可能编写一个方法来接受一个列表??空字符串并以任何方式适当地操作(因此您可以传入一个可空字符串或不可空字符串的列表,您的方法并不关心,同时您仍然可以同时获取(可空)字符串并添加xs,其中x是已知的非空字符串,或者(可能)从该列表中获取的空字符串。不变、协变和逆变的概念往往适用于所有类型关系和标记,空值是一个标记,就像“此列表包含字符串”是一个标记一样。

相关问题