Examples of Unconventional Usage of Suppress in Kotlin

  • 2021-10-25 07:43:58
  • OfStack

Preface

In Java, there is an annotation called SuppressWarnings to ignore specific compiler warnings. Kotlin also has a similar function of the annotation, called Suppress, this article mainly talks about the use of this annotation.

Conventional usage

Sometimes I write such a code. This code, which may have problems in the eyes of Kotlin compiler, is actually very correct and will run without any problems.

Then you get a compiler warning (warning) or even a compilation error (error).

More common, such as unchecked cast:


val some: List<*> = emptyList<Nothing>()
some as List<String> // Unchecked cast: List<*> to List<String>

You can then cancel this warning using Suppress:


val some: List<*> = emptyList<Nothing>()
@Suppress("UNCHECKED_CAST")
some as List<String>

Another example:


sealed class Base {
 @Suppress("LeakingThis")
 val code = calculate()
 abstract fun calculate(): Int

 class Derived : Base() {
  override fun calculate() = 42
 }
}

The above code does not appear warning specific description of the problem, so the use of Suppress to solve this warning.

This is very simple broken water, and there is no value for discussion.

Then the following is the text.

Good boy, don't imitate! It's dangerous!

Unconventional usage

This stupid annotation can eliminate error!

For example, this code:


println((null as String?).length)

The compiler will tell you that this is wrong, and then throws you an error:

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

Then you can use Suppress to shut up the compiler!


@Suppress("UNSAFE_CALL")
println((null as String?).length)

Then you can successfully pass the compilation. After compiling, you can easily get a null pointer exception by running 1 run:

Exception in thread "main" java.lang.NullPointerException
at .......

Quite simply, with Suppress, you can make the code that could have been generated by the compiler by java bytecode, but was dropped by ban for various reasons (such as type safety), pass the compilation smoothly.

Here are a few examples that may be useful.

Example 1


fun some(any: Any) {
 when(any) {
  is Array<String> -> println(any.size)
 }
}

This is the first in the series "What Java can do but Kotlin can't do". Regardless of other target of Kotlin (such as js), there are the following circuitous on Jvm platform:


any is Array<*> && any.isArrayOf<String>()

It's just ugly.

In the early code of Kotlin, such type check was allowed, because ban was dropped for some reason (readers can think about why ban dropped such code). At this time, you can open the back door with Suppress.


@Suppress("CANNOT_CHECK_FOR_ERASED")

Example 2

Type alias.


class Some {
 @Suppress("TOPLEVEL_TYPEALIASES_ONLY")
 typealias Str = String

 val a: Str = ""
}

1 clear, do not explain.

Example 3

Kotlin adds the lateinit modifier to the ancient version M13, which can be used for read-only attributes and variable attributes.

Then M14 cruelly dropped ban lateinit val.


@Suppress("INAPPLICABLE_LATEINIT_MODIFIER")
lateinit val lateInitVal: String

The use of lateinit val can be found in the link to M13 above.

Example 4

Kotlin Collection Literals semi-finished.


val some: List<*> = emptyList<Nothing>()
@Suppress("UNCHECKED_CAST")
some as List<String>
0

This is an unfinished function, which only supports arrays at present. List, Map, and Set can be supported later, so in order to avoid unnecessary compatibility troubles, this is normally allowed only in comments. If you want to use it elsewhere, just like the above code.

End

If you want to know more Suppress options, you can turn over the source code of Kotlin.

This kind of strange skill, which can't get official support, may be hung up next time it is updated, so if it is used, it will be at your own risk.

Summarize


Related articles: