标签: kotlin-null-safety

Kotlin对类属性的null安全性

如何避免使用!!类的可选属性

class PostDetailsActivity {

    private var post: Post? = null

    fun test() {
        if (post != null) {
            postDetailsTitle.text = post.title    // Error I have to still force using post!!.title
            postDetailsTitle.author = post.author

            Glide.with(this).load(post.featuredImage).into(postDetailsImage)

        } else {
            postDetailsTitle.text = "No title"
            postDetailsTitle.author = "Unknown author"

            Toast.makeText(this, resources.getText(R.string.post_error), Toast.LENGTH_LONG).show()
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我应该创建一个局部变量吗?我认为使用!!不是一个好习惯

null kotlin kotlin-null-safety

4
推荐指数
1
解决办法
113
查看次数

Kotlin .let {} null安全假设错误

使用该.let { }功能时,我注意到在执行以下操作时:

bucket?.assignedVariantName.let {
        bucket?.determineVariant()  <-- guarantee safety for bucket
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下你必须保证铲斗的安全,即 bucket?.或者bucket!!在使用?.let时已经保证了零安全性,然后我注意到在执行以下操作时:

bucket?.assignedVariantName?.let { <-- added safety check for property 
        bucket.determineVariant()  <-- doesn't need to guarantee safety for bucket
}
Run Code Online (Sandbox Code Playgroud)

虽然在桶的属性上使用let而不是直接在桶上我想知道这是故意还是Kotlin插件中的错误(在这种情况下我在Android Studio中遇到过这个)

另外的信息是,在这种情况下,存储桶是一个已local val分配的变量名是可以为空的变量.

val bucket: T? = ...
Run Code Online (Sandbox Code Playgroud)

kotlin kotlin-null-safety

4
推荐指数
1
解决办法
690
查看次数

Kotlin:不能同时应用两个条件检查"返回体"功能样式

我有一个简单的功能检查,如下所示:

    fun parseValidBluetoothBrickedId(controllerId: String?): Boolean{
    if(controllerId != null){
        if(controllerId.startsWith(BLUETOOTH_NAME_PREFIX) && controllerId.length > BLUETOOTH_NAME_PREFIX.length)
            return true
    }

    return false
}
Run Code Online (Sandbox Code Playgroud)

我想将它转换为更简单的风格:

   fun parseValidBluetoothBrickedId(controllerId: String?) =
        controllerId?.length > BLUETOOTH_NAME_PREFIX.length
      &&  controllerId?.startsWith(BLUETOOTH_NAME_PREFIX)
Run Code Online (Sandbox Code Playgroud)

但IDE(Android Studio 3.0 Beta7)给我一个错误,强调大于('>')运算符:

操作员调用对应于点限定调用'controllerId?.length.compareTo(BLUETOOTH_NAME_PREFIX.length),此处不允许

它还强调为错误行controllerId?.startsWith(BLUETOOTH_NAME_PREFIX)并说:

类型不匹配.必需:Boolean,Found Boolean?

有什么问题,真的吗?它只是一个简单的方法,适用于第一个块if-else风格.

kotlin kotlin-null-safety

4
推荐指数
1
解决办法
1838
查看次数

在可空的接收器类型的arraylist上只允许安全或非空的assserted调用

刚刚开始使用kotlin进行android开发.我的arraylist被宣布为这样 -

var day1: ArrayList<DietPlanDetailModel>? = null
Run Code Online (Sandbox Code Playgroud)

现在我试图通过它的位置访问一个元素

    val dietPlan= day1[position]
Run Code Online (Sandbox Code Playgroud)

但我在编译时错误 -

在可空的接收器类型的arraylist上只允许安全或非空的assserted调用

为什么我会收到此错误,我该如何解决?

android kotlin kotlin-null-safety

4
推荐指数
2
解决办法
1万
查看次数

kotlin逆布尔安全铸造

假设我有一个对象Response.现在我想检查一个布尔变量,成功,在Response下并做一个早期返回是响应不成功.

if(response == null || !response.success){
   return;
} //Java version
Run Code Online (Sandbox Code Playgroud)

现在我想使用Kotlin的null安全检查,如下所示

if(response?.success ?: true){
    return
}
Run Code Online (Sandbox Code Playgroud)

如果我没有错,如果响应或成功为null,我们将在if条件内返回true.但是,如果response.success不为null且等于true,我们仍将从函数返回,这不是我想要的.我该如何纠正这种情况?

null-check kotlin kotlin-null-safety

4
推荐指数
1
解决办法
1065
查看次数

Kotlin !! 操作员使用使代码不清晰

我正在写一个Kotlin应用程序,我一直在研究这种语言,我注意到要创建一个变量,你必须明确定义它是否为null然后你使用?运营商.

现在,我的问题.有时我必须定义一个全局变量(在这种情况下是一个片段),所以我需要将它设为null,因为我还不能初始化它

在java中我没有这个问题,因为在声明它之后我做的第一件事是在onCreate()中初始化像这样

TurboFragment fragment = null;

@Override
public void onCreate(Bundle savedInstanceState) {

    ...

    fragment = adapter.getCurrentFragment();
}
Run Code Online (Sandbox Code Playgroud)

然后我可以在没有语法问题的情况下使用它在Kotlin中是不同的,因为我必须这样做

private var fragment: TurboFragment? = null

override fun onCreate(savedInstanceState: Bundle?) {

    ...

    fragment = adapter!!.currentFragment
    fragment!!.foo()
    var x = fragment!!.sampleInt
}
Run Code Online (Sandbox Code Playgroud)

现在,每次我调用片段的实例时我都必须使用null-safe !! 运营商.这使我的代码变得混乱,因为对于每一行,我至少有一个!运算符,它看起来真的不清楚它是否如此频繁,特别是如果你有5个或更多这样的变量.有没有办法简化代码或这种语言的性质是这样的?

null android kotlin kotlin-null-safety

4
推荐指数
1
解决办法
106
查看次数

Kotlin项目中使用的旧Java库中的空安全性

假设我在旧/遗留Java库中有特定代码:

public class JavaClass {
    private String notNullString;
    private String nullableString;
    private String unannotatedString;

    public JavaClass(@NotNull String notNullString,
                     @Nullable String nullableString,
                     String unannotatedString) {

        this.notNullString = notNullString;
        this.nullableString = nullableString;
        this.unannotatedString = unannotatedString;
    }

    @NotNull
    public String getNotNullString() {
        return notNullString;
    }

    @Nullable
    public String getNullableString() {
        return nullableString;
    }

    public String getUnannotatedString() {
        return unannotatedString;
    }
}
Run Code Online (Sandbox Code Playgroud)

前两个参数使用@NotNull和@Nullable注释正确注释(使用jetbrains.annotations).第三个(unnanotatedString)没有正确的注释.

当我在我的Kotlin代码中使用这个类并将所有构造函数参数设置为非null值时,一切都很好:

val foo = JavaClass("first string", "second string", "third string")

println("Value1: ${foo.notNullString.length}")
println("Value2: ${foo.nullableString?.length}")
println("Value3: ${foo.unannotatedString.length}")
Run Code Online (Sandbox Code Playgroud)

第一个值是非null,所以我可以在没有安全调用的情况下访问它.第二个值我需要使用安全调用(nullableString?.length),如果没有,我有一个编译时错误,到目前为止一直很好.在第三个值(unannotatedString)我可以在没有安全调用的情况下使用它,它编译得很好.

但是当我将第三个参数设置为"null"时,我没有得到编译时错误(不需要安全调用,只有运行时NullPointerException:

val …
Run Code Online (Sandbox Code Playgroud)

java annotations kotlin kotlin-interop kotlin-null-safety

3
推荐指数
2
解决办法
625
查看次数

为什么 Kotlin 在反编译为 Java 时会进行空检查声明一些未使用的变量?

我在 JVM 11 上使用 Kotlin 1.5.20 做了以下操作(AdoptOpenJDK build 11.0.4+11)

通常在 Kotlin 中,我会执行偏向x?.let {}x?.run {}超过if(x != null) {}. 我将这三种方法反编译为 Java,以了解我最喜欢的方法是否会引入任何类型的低效率。反编译这个 Kotlin 代码

class Main {
    fun main1(x: String?){
        x?.run { println(this) }
    }

    fun main2(x: String?){
        x?.let { x1 -> println(x1) }
    }

    fun main3(x: String?){
        if (x != null){
            println(x)
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

我得到这个 Java 代码

@Metadata(
   mv = {1, 5, 1},
   k = 1,
   d1 = {"\u0000\u001a\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\b\u0002\n\u0002\u0010\u0002\n\u0000\n\u0002\u0010\u000e\n\u0002\b\u0003\u0018\u00002\u00020\u0001B\u0005¢\u0006\u0002\u0010\u0002J\u0010\u0010\u0003\u001a\u00020\u00042\b\u0010\u0005\u001a\u0004\u0018\u00010\u0006J\u0010\u0010\u0007\u001a\u00020\u00042\b\u0010\u0005\u001a\u0004\u0018\u00010\u0006J\u0010\u0010\b\u001a\u00020\u00042\b\u0010\u0005\u001a\u0004\u0018\u00010\u0006¨\u0006\t"},
   d2 = {"Lcom/cgm/experiments/Main;", "", "()V", "main1", …
Run Code Online (Sandbox Code Playgroud)

java null null-check kotlin kotlin-null-safety

3
推荐指数
1
解决办法
88
查看次数

为什么 Kotlin 的 null 安全性不能与局部变量初始化器一起正常工作?

请看这段代码:

fun localVarNullSafety1(){
    var number: Double? = 3.0

    val sum = 2.0 + number // does not compile (Type mismatch: inferred type is Double? but Double was expected)
}

fun localVarNullSafety1(){
    var number: Double? = null
    
    number = 3.0

    val sum = 2.0 + number // compiles fine
}
Run Code Online (Sandbox Code Playgroud)

我认为上面的代码由语义上相同的函数组成 - 局部变量不会超出范围,并且它们对于执行线程来说是本地的。在我看来,第一个函数没有理由不编译。

我认为 Kotlin 的智能转换应该考虑变量初始化。

我错过了一些明显的事情吗?

language-design kotlin kotlin-null-safety

3
推荐指数
1
解决办法
104
查看次数

从 Kotlin 调用 Java 方法时如何安全地处理 null 值?

当与没有 null 安全性的 Java 库交互时,如何在 Kotlin 中处理 null 安全性?

通过研究,我发现以下一些东西“有效”,但并不安全。

  1. 将 Kotlin 的非 null 类型与返回 null 的 Java 方法结合使用:

  2. !!将运算符与返回 null 的 Java 方法一起使用:

  3. 假设 Java 布尔值永远不为 null:在 Java 中,Boolean可以是true, false, 或null,但在 Kotlin 中,Boolean只能是truefalse

在这些示例中,我的 Kotlin 编译器不会显示错误,因为它没有足够的关于 Java 方法是否可以返回 null 的信息。

java nullpointerexception kotlin kotlin-null-safety

3
推荐指数
1
解决办法
324
查看次数