Effective Kotlin: Methods

Let’s see how we can apply Joshua Bloch’s Effective Java in the Kotlin world. Today’s topic is Methods.

Item 49: Check parameters for validity

Kotlin introduced contracts in 1.3 to help cases when we validate parameters in a separate function.

For example, the CharSequence?.isNullOrEmpty() extension function provides the contract that when false is returned, the receiver is not null. As a result, we can use smartcast like below:

fun foo(str: String?) {
  if (str.isNullOrBlank()) return

  // thanks to the contract, the smartcast is possible here

Also, when developing Android, we can use annotations like IntRange to help validate parameters.

Item 50: Make defensive copies when needed

This is nothing special in Kotlin for this item.

Item 51: Design method signatures carefully

When calling methods with long parameter lists, consider using named arguments, e.g.:

// suppose we have this function
fun name(firstName: String, middleName: String, lastName: String, suffix: String) {

// we can call it like below
  firstName = "Xizhi",
  middleName = "",
  lastName = "Zhu",
  suffix = ""

Item 52: Use overloading judiciously

This is nothing special in Kotlin for this item.

Item 53: Use varargs judiciously

Be aware that in Kotlin, the spread operator (*) always makes a copy of the array.

Item 54: Return empty collections or arrays, not nulls

Unless we explicitly mark the return type as nullable, we can only return non-null types, which is preferred.

Item 55: Return optionals judiciously

In Kotlin, we can simply return a nullable type. It provides null safety at compile time, has no runtime overhead (except for nullable primitive types), and comes with lots of operators (such as let() and takeIf()) to make the code more readable, e.g.:

  ?.takeIf { it.isNotBlank() }
  ?.let { println(it) }

Item 56: Write doc comments for all exposed API elements

As expected, Kotlin comes with nice tool for documentation.

See also