Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

450
Vistas
Kotlin: equal comparison seems OK on nullable, but greater than comparison is not

I am new to Kotlin. I am following along a tutorial where the GUI portion involves this code snippet:

    sampleList.addMouseListener(object: MouseAdapter() {
        override fun mouseClicked(mouseEvent: MouseEvent?) {
            if (mouseEvent?.clickCount == 2) {
                launchSelectedSample()
            }
        }
    })

mouseEvent is obviously something nullable. I am used to, in previous coding experience, changing a line like mouseEvent?.clickCount == 2 to mouseEvent?.clickCount > 1 (or maybe >=2), to ensure there is no corner case where the clicks happen so quickly that it jumps from 1 to 3, or something similar.


So, I switched this code to:

    sampleList.addMouseListener(object: MouseAdapter() {
        override fun mouseClicked(mouseEvent: MouseEvent?) {
            if (mouseEvent?.clickCount >= 2) {
                launchSelectedSample()
            }
        }
    })

Upon making the switch (changing ==2 to >=2), I received the following error from IntelliJ:

Operator call corresponds to a dot-qualified call 'mouseEvent?.clickCount.compareTo(2)' which is not allowed on a nullable receiver 'mouseEvent?.clickCount'.

This raised 2 questions for me:

  1. Why does ==2 work fine, but >=2 does not work? (I tried >1, which gave the same error as >=2.)
  2. What is the right way to handle a corner case where, what I really want is anything greater than 1?

I like the idea of ensuring nulls don't screw things up during runtime, but I kinda wish if Kotlin just got rid of null values altogether and did something like Rust or Haskell. (I do like what I've seen of Kotlin so far, though.)

over 4 years ago · Santiago Trujillo
3 Respuestas
Responde la pregunta

0

As you've found, Kotlin's equality operators (== and !=) can handle nulls, while the order comparison operators (<, <=, >, >=) can't.

This is probably because it's obvious what equality checks should mean for nulls — two nulls are clearly equal, and a non-null value should never equal a null — while it's not at all clear what it should mean for order comparisons.  (If null isn't < 0, does that mean null >= 0?  If not, you no longer have a well-defined ordering.)

This is reflected in the implementation: Any has an equals() method, indicating that all objects can be checked for equality.  (Kotlin's documentation makes it explicit, as does that for the underlying Java method, that non-null objects must never equal null.)  And Kotlin's implementation of the == and != operators explicitly checks for nulls.  (a == b translates to what you have to spell out in Java: a == null ? b == null : a.equals(b).)

But order comparison is handled differently.  It uses the Comparable interface: only types with a ‘natural ordering’ implement that; those that don't, can't be compared in that way.  Since null can't implement any interfaces, it can't have a natural ordering, and the compiler prevents you trying the comparison.  (Kotlin's documentation doesn't make this explicit, because the parameter is non-nullable; but that for the underlying Java interface says that such a comparison should return a NullPointerException.)

As to how you should handle this, the Elvis operator is probably the most concise solution:

if (mouseEvent?.clickCount ?: 0 >= 2)

If mouseEvent is not null, this will get its clickCount; otherwise, the safe-call ?. will give the null directly, and then the ?: will substitute 0.  (That would also happen if the clickCount held null, though that shouldn't be possible.)  In every case, you end up with a non-nullable integer that can safely be compared with 2.

Of course, in practice, nothing should ever be calling a listener method and passing a null event.  (I can't recall ever allowing for that back when I used to write Java Swing code for a living, or hitting any problems as a result.)  So a simpler alternative might be declaring the parameter as non-nullable.  But handling the null properly is just that little bit safer; and in this case, it doesn't add much extra code.  So it's up to you!

over 4 years ago · Santiago Trujillo Denunciar

0

What behavior from mouseEvent?.clickCount >= 2 do you expect when mouseEvent == null ?

You could transform your mouseEvent?.clickCount to NotNull using elvis (?:) operator:

val clickCount = mouseEvent?.clickCount ?: 0
if (clickCount >= 2) {
    launchSelectedSample()
}

In this case mouseEvent?.clickCount will be 0 if mouseEvent is null

==2 works because mouseEvent?.clickCount considered by Kotlin as null and comparison null == 2 is correct unlike null >= 2

over 4 years ago · Santiago Trujillo Denunciar

0

a little bit more kotlin style can be this:

mouseEvent?.clickCount?.let{ 
  if(it >= 2) {
    launchSelectedSample()
  }
}

even more functional style:

mouseEvent?.clickCount?.takeIf { it >= 2 }?.let { launchSelectedSample() }
over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda