Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

450
Visualizações
Kotlin extension functions - Difference between Any? and Generic T?

I was doing some coding for fun and I was wonder which one should I use. Tried both and they gave me the same result. So, what's the difference between the two?

Examples:

fun Any?.foo() = this != null

fun <T> T?.foo() = this != null

The actual function is a bit more complicated and it actually does something based on the real type of the object (like a when with some options)

over 4 years ago · Santiago Trujillo
2 Respostas
Responde à pergunta

0

The second function gives you an opportunity that is not used in this particular case: it captures the type of the receiver into the type parameter T, so that you may use it somewhere else in the signature, like in the parameter types or the return value type, or in the function body.

As a quite synthetic example, a listOf(this, this) inside the second function would be typed as List<T?>, retaining the knowledge that the items type is the same as the receiver type, while the same expression in the first function would be a List<Any?>.

The first function does not allow you to use the receiver type generically for storing items of this type, accepting additional items of the same type as parameters or using the receiver type in the return value type of the function, while the second function allows all of these.

These functions are equivalent from the runtime perspective, as generics are erased from the JVM bytecode when the code is compiled, so you won't be able to determine the type T at runtime and act depending on it, unless you convert the function to an inline function with a reified type parameter.


As a very important special case, capturing the type from a call site into a type parameter allows a higher-order function to accept another function using T in its signature. The standard library has a set of scoping functions (run, apply, let, also) which show the difference.

Suppose that the signature of also did not use generics and looked like this:

fun Any?.also(block: (Any?) -> Unit): Any? { ... }

This function can be called on any object, but its signature doesn't show that it's the receiver object that is passed to the block and returned from the function – the compiler won't be able to ensure type safety and, for example, allow a call to a member of the receiver object without a type check:

val s: String = "abc"

// won't compile: `it` is typed as `Any?`, the returned value is `Any?`, too
val ss1: String = (s + s).also { println(it.length) } 

// this will work, but it's too noisy
val ss2: String = (s + s).also { println((it as String).length) } as String 

Now, capturing the type parameter is exactly the way to show that it is the same type in all the three places. We modify the signature as follows:

fun <T : Any?> T.also(block: (T) -> Unit): T { ... }

And the compiler can now infer the types, knowing that it's the same type T everywhere it appears:

val s: String = "abc"

// OK!
val ss: String = (s + s).also { println(it.length) } 
over 4 years ago · Santiago Trujillo Relatório

0

If you run this on the JVM you will get the following

java.lang.ClassFormatError: Duplicate method name&signature in class file ...

This is interesting, so from a signature standpoint they are identical.

It strongly depends on your use case, but in most cases you may want to use the generic variant, because the type may be variable but fixed at compile-time. This advantage becomes obvious here:

fun Any?.foo() = this
fun <T> T?.bar() = this

fun main(args: Array<String>) {
    val x = 5.foo() // Any?
    val y = 5.bar() // Int?
}

All properties and functions available on Int? won't be usable for x until I explicitely cast it (to and Int?). y on the other hand "knows" that it returned an Int?.


In your example it wouldn't make a difference since you will always return a Boolean and as already shown, the signature are the same.

over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda