V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
winterbells
V2EX  ›  Kotlin

屎山代码一则

  •  
  •   winterbells · 86 天前 · 2656 次点击
    这是一个创建于 86 天前的主题,其中的信息可能已经有所发展或是发生改变。

    大家都知道 Kotlin 有空安全

    var s: String 代表不为空

    var s: String? 代表可为空

    奇葩操作来了,在我接手之前,除了绝大部分的基本变量,其余所有变量都是 String?、Objxx?

    使用的时候:

    if (S != null) print(s) else throw Exption("s shouldn't be null")
    

    或者:

    if (obj?.s == null) return
    obj!!.s
    

    一开始很好奇这个脑残写法是怎么来的

    然后遇到了一个 crash 我找到根源了。我写的代码里没有用 String? ,但是却报了 NPE ,赋值的地方都查过了,不存在 null 。最终不断地调试发现每次页面 onDestory()的时候会有个反射递归地将所有变量和变量里的变量都设置成 null (说是在手动 GC…)。又因为魔改了生命周期+协程,读取变量的时候已经是 null 了,然后报错==

    16 条回复    2024-10-07 14:06:42 +08:00
    ghost024
        1
    ghost024  
       86 天前
    哈哈哈哈哈,要么改反射,要么加入:)
    nuonuojump
        2
    nuonuojump  
       86 天前
    挺先进的代码,我都没想过还能在销毁的时候 手动做这种类型的 gc 。挺先进的。
    easylee
        3
    easylee  
       86 天前
    如此一说,Java 里面是不是也能这么操作?有实战案例吗!
    htxy1985
        4
    htxy1985  
       86 天前   ❤️ 2
    手动设置为 null 这种做法只在零几年的代码里见过,还有人专门写了英文注释,感觉是跟国际水准接轨 /doge
    beisilu
        5
    beisilu  
       85 天前
    盲猜这个是在已有屎山上拉的
    盲猜楼主还要再拉一坨
    winterbells
        6
    winterbells  
    OP
       85 天前 via Android
    @ghost024 改是不会改的,能想象无止境的追问改这个有什么意义


    @beisilu 不拉了,我选择加入。万一出了问题还得我改
    akiakise
        7
    akiakise  
       85 天前 via iPhone
    简直就是在用 java 的方式写 kotlin ,jb 辛辛苦苦加的那么多语法糖是一口不吃啊
    winterbells
        8
    winterbells  
    OP
       85 天前
    @akiakise 有些地方还是吃的,但绝大多数代码都是 Java 的风格

    另外我们是 Android ,官方组件几乎不用的。viewmodel 、lifecycler 什么的。自己搓了一套 lifestate ,从来没去研究过到底解决了什么问题,难懂反正
    leegradyllljjjj
        9
    leegradyllljjjj  
       85 天前
    java 就是上世纪的狗屎语言,不少遗老遗少还当宝,自诩为 java 专家称号
    iseki
        10
    iseki  
       84 天前 via Android
    这已经不是什么语言的问题了😩不过我大概猜测,是不是哪里一直持有这个 activity 的引用啊,要不然怎么会想到干这种事
    winterbells
        11
    winterbells  
    OP
       84 天前 via Android
    @iseki 乱七八糟的引用也是原因之一,但是这个回收代码一开始就有
    lisongeee
        12
    lisongeee  
       84 天前
    ```kt
    if (obj?.s == null) return
    obj!!.s
    ```
    我一般不会这么写,我一般写的是
    ```kt
    val s = obj?.s ?: return
    ```
    这样才能保证线程安全,最上面那种情况我只会在 js 里写,只有在 js 里这种用法才是线程安全的 (瞎写的 getter 不算)
    winterbells
        13
    winterbells  
    OP
       84 天前
    @lisongeee 我这边看到两种写法都有,更多的是
    val o = obj ?: return

    coroutine / callback{
    o.xxx
    }

    这里还拿了个引用
    lisongeee
        14
    lisongeee  
       84 天前
    val s 是线程安全的,obj!!.s 是线程不安全的

    如果 obj 是 val 的,并且 obj 的 s 也是 val 声明的,那 val s 和 obj.s 没区别

    如果你的代码风格尽量向 immutable 靠近,那能避免很多错误,当然这是我的前端思维,我不知道是否适合后端

    可以了解一下 kotlinx-collections-immutable 这个库
    xuanbg
        15
    xuanbg  
       84 天前
    @leegradyllljjjj 这个和语言有什么关系啊,你给个你心目中最好的语言,我负责给你找一堆的屎来喂给你
    winterbells
        16
    winterbells  
    OP
       84 天前 via Android
    @lisongeee 没毛病,安卓也是前端😄
    obj.s 可能是 val 也可能是 var 也可能是方法
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1333 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 17:37 · PVG 01:37 · LAX 09:37 · JFK 12:37
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.