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的源码。

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

总结

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

(0)

相关推荐

  • Kotlin 基础教程之注解与java中的注解比较

    Kotlin 的注解完全兼容 Java 的注解. 声明注解 @Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.EXPRESSION) @Retention(AnnotationRetention.SOURCE) @MustBeDocumented annotation class Fancy 可以通过向注解类添加元注解(meta

  • Kotlin基础学习之Deprecated与Suppress注解使用

    前言 在 Java 中通常对一些方法进行一些注解操作,但是很多注解在 Java 代码上没有问题,如果切换到 Kotlin 上时,如果继续使用这些注解就会存在一些问题,本篇主要对比一些常用 Java 注解和 Kotlin 注解使用转换. Deprecated 在 Java 方法中,如果需要废弃一个方法,只需要在方法钱加上 @Deprecated 即可,例如这样: @Deprecated public void test(){ } 但是如果在 Kotlin 代码中直接使用这个注释,就存在问题了: D

  • Kotlin 的注解类详解及实例

    Kotlin 的注解类详解及实例 注解声明 注解是将元数据附加到代码的方法.要声明注解,请将 annotation 修饰符放在类的前面: annotation class Fancy 注解的附加属性可以通过用元注解标注注解类来指定: @Target 指定可以用 该注解标注的元素的可能的类型(类.函数.属性.表达式等): @Retention 指定该注解是否 存储在编译后的 class 文件中,以及它在运行时能否通过反射可见 (默认都是 true): @Repeatable 允许 在单个元素上多次

  • Kotlin中Suppress的非常规用法示例

    前言 在 Java 中,有个叫 SuppressWarnings 的注解,用于忽略特定的编译器警告.Kotlin 中也有一个类似功能的注解,叫做 Suppress,本文主要讲讲这个注解有什么用. 常规用法 有时候会写出这样的一些代码.这些在Kotlin编译器的眼里可能出现问题的代码,实际上却非常正确,跑起来不会出任何问题. 然后你就得到了一个编译器警告(warning),甚至是编译错误(error). 比较常见的,比如说 unchecked cast: val some: List<*> =

  • Java中枚举类的用法示例详解

    目录 1.引入枚举类 2.实现枚举类 3.枚举类的使用注意事项 4.枚举的常用方法 5.enum细节 1.引入枚举类 Java 枚举是一个特殊的类,一般表示一组常量,比如一年的 4 个季节,一个年的 12 个月份,一个星期的 7 天,方向有东南西北等. Java 枚举类使用 enum 关键字来定义,各个常量使用逗号 , 来分割. 示例: enum Color { RED, GREEN, BLUE; } 2.实现枚举类 接下来我们来看一个一个简单的DEMO示例: /** * java枚举 */ p

  • 谈谈Spring AOP中@Aspect的高级用法示例

    前言 本文主要跟大家分享介绍了关于Spring AOP中@Aspect的高级用法,下面话不多说了,来随着小编一起看看详细的介绍吧. 1 切点复合运算 支持在切点定义中加入以下运算符进行复合运算: 运算符 说明 && 与运算. ! 非运算. || 或运算. 2 切点命名 一般情况下,切点是直接声明在需要增强方法处,这种切点的声明方式称为匿名切点,匿名切点只能在声明处被使用 . 如果希望在其它地方可以重用这个切点,我们可以通过 @Pointcut 注解及切面类方法来命名它. public cl

  • Kotlin中的5种单例模式示例详解

    前言 最近在学习Kotlin这门语言,在项目开发中,运用到了单例模式.因为其表达方式与Java是不同的.所以对不同单例模式的实现进行了分别探讨.主要单例模式实现如下: 饿汉式 懒汉式 线程安全的懒汉式 双重校验锁式 静态内部类式 PS:该篇文章不讨论单例模式的运用场景与各种模式下的单例模式的优缺点.只讨论在Java下不同单例模式下的对应Kotlin实现. 一.饿汉式实现 //Java实现 public class SingletonDemo { private static SingletonD

  • jQuery中内容过滤器简单用法示例

    本文实例讲述了jQuery中内容过滤器简单用法.分享给大家供大家参考,具体如下: 一 介绍 内容过滤器就是通过DOM元素包含的文本内容以及是否含有匹配的元素进行筛选.内容过滤器共包括:contains(text).:empty.:has(selector)和:parent4种,如下表所示. 过滤器 说明 示例 contains(text) 匹配包含给定文本的元素 $("li:contains('DOM')")    //匹配含有"DOM"文本内容的li元素 :emp

  • jQuery中过滤器的基本用法示例

    本文实例讲述了jQuery中过滤器的基本用法.分享给大家供大家参考,具体如下: HTML正文: <input type="button" id="b1" value="偶数行红色"><br> <input type="button" id="b2" value="奇数行绿色"><br> <table border=1 width=&q

  • jQuery中extend函数简单用法示例

    本文实例讲述了jQuery中extend函数简单用法.分享给大家供大家参考,具体如下: var result=$.extend({},item,item1); extend给对象添加新的属性:js插件经常使用来配置参数 {}:item和item1合并后的结果 item:默认属性 item1:新增属性,如果item1和item属性重合则会覆盖item1中的属性 <span id="Test"></span> var item={"name":&

  • ASP.NET MVC中使用JavaScriptResult的用法示例

    本文实例讲述了ASP.NET MVC中使用JavaScriptResult的用法.分享给大家供大家参考,具体如下: 在页面中我们使用JavaScript来设置id为qubernet的span标签样式,具体代码如下: JS: <script> $(function () { var thisObj = document.getElementById("qubernet"); thisObj.setAttribute("style", "color

  • golang中strconv.ParseInt函数用法示例

    本文实例讲述了golang中strconv.ParseInt函数用法.分享给大家供大家参考,具体如下: golang strconv.ParseInt 是将字符串转换为数字的函数,功能灰常之强大. 参数1 数字的字符串形式 参数2 数字字符串的进制 比如二进制 八进制 十进制 十六进制 参数3 返回结果的bit大小 也就是int8 int16 int32 int64 func ParseInt(s string, base int, bitSize int) (i int64, err erro

  • C#中this指针的用法示例

    本文实例展示了C#中this指针的用法,对于初学者进一步牢固掌握C#有很大帮助,具体内容如下: 一.this指针是什么: 这里有一些面向对象编程的概念需要说明:类(Class)的概念和对象(Object)的概念 类是对事物概括,也是C#编码时所有代码归属的基本单位:而对象是对类的实例化,也就是C#里new方法的返回值.写代码是不能直接用操作类,而只能先实例化类,然后我们用这个类被实例化后的对象. 通俗一些的说明是,"类"好比是"人"的概念,而我们把类实例化后,就成为

随机推荐