欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Kotlin中Suppress的非常规用法示例

程序员文章站 2023-02-07 15:27:41
前言 在 java 中,有个叫 suppresswarnings 的注解,用于忽略特定的编译器警告。kotlin 中也有一个类似功能的注解,叫做 suppress,本文主...

前言

在 java 中,有个叫 suppresswarnings 的注解,用于忽略特定的编译器警告。kotlin 中也有一个类似功能的注解,叫做 suppress,本文主要讲讲这个注解有什么用。

常规用法

有时候会写出这样的一些代码。这些在kotlin编译器的眼里可能出现问题的代码,实际上却非常正确,跑起来不会出任何问题。

然后你就得到了一个编译器警告(warning),甚至是编译错误(error)。

比较常见的,比如说 unchecked cast:

val some: list<*> = emptylist<nothing>()
some as list<string> // unchecked cast: list<*> to list<string>

然后就可以使用 suppress 取消这个 warning:

val some: list<*> = emptylist<nothing>()
@suppress("unchecked_cast")
some as list<string>

再举个例子:

sealed class base {
 @suppress("leakingthis")
 val code = calculate()
 abstract fun calculate(): int

 class derived : base() {
  override fun calculate() = 42
 }
}

上面这代码并不会出现 warning 的具体说明里的问题,所以使用了 suppress 解决这个 warning。

这是很简单的破事水,没有任何讨论的价值。

然后下面是正文。

好孩子不要模仿!很危险的!

非常规用法

这破注释竟然能消除 error!

比如说这样的代码:

println((null as string?).length)

编译器会告诉你这样是不对的,然后向你丢出了一个 error:

only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type string?

然后就可以使用 suppress 让编译器闭嘴!

@suppress("unsafe_call")
println((null as string?).length)

然后就可以顺利的通过编译,编译后跑一跑,就可以轻松地拿到一个空指针异常:

exception in thread "main" java.lang.nullpointerexception
    at .......

很简单,有了 suppress,你就可以让这些可以本来通过编译器生成java字节码,但是因为各种各样的原因(例如类型安全)被ban掉的代码,顺利通过编译。

下面给几个可能有用的例子。

例1

fun some(any: any) {
 when(any) {
  is array<string> -> println(any.size)
 }
}

这是我吐槽过的「java能做但是kotlin做不了的事」系列之一。不考虑kotlin的其他target(如js),在jvm平台上有如下的迂回:

any is array<*> && any.isarrayof<string>()

就是很丑罢了。

在kotlin的早期代码,这样的type check是允许的,因为某些原因ban掉了(读者可以想想为什么要ban掉这样的代码)。这个时候可以用 suppress 把这个后门打开。

@suppress("cannot_check_for_erased")

例2

类型别名。

class some {
 @suppress("toplevel_typealiases_only")
 typealias str = string

 val a: str = ""
}

一目了然,不解释。

例3

kotlin 在远古版本 m13 新增了 lateinit 修饰符,可以对只读属性和可变属性使用。

然后 m14 版本就残忍地 ban 掉了 lateinit val。

@suppress("inapplicable_lateinit_modifier")
lateinit val lateinitval: string

lateinit val 的用处可以看上面 m13 的链接里面的说明。

例4

kotlin collection literals 半成品。

@suppress("unsupported")
val bs: booleanarray = [true, false, true]

这是个未完成的功能,目前只支持数组。以后可以支持 list、map 和 set,所以为了避免不必要的兼容性麻烦,在正常情况下只允许在注解里这样用。要想在其他地方用,就像上面代码那样。

结尾

想知道更多的suppress选项的话,可以去翻kotlin的源码。

这种无法得到官方支持的奇技淫巧,也许下次更新就挂掉了,所以如果用了那就后果自负吧。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对的支持。