La mejor manera de “negar” una instancia de

4 minutos de lectura

avatar de usuario
caarlos0

Estaba pensando si existe una forma mejor/mejor para negar un instanceof en Java. En realidad, estoy haciendo algo como:

if(!(myObject instanceof SomeClass)) { /* do Something */ }

Pero creo que debería existir una sintaxis “hermosa” para hacer esto.

¿Alguien sabe si existe y cómo se ve la sintaxis?


EDITAR:
Por hermoso, podría decir algo como esto:

if(myObject !instanceof SomeClass) { /* do Something */ } // compilation fails

  • Odio las reglas de precedencia para instanceof mucho…

    – luiscubal

    30 de enero de 2012 a las 17:38

  • Siempre puedes crear una variable, algo como boolean strIsString = str instanceof String;

    – vaughandroid

    30 de enero de 2012 a las 17:42

  • si @Baqueta, es una opción. Pero, ¿qué diferencias pueden darse en el uso de la memoria en una sintaxis u otra?

    – caarlos0

    30 de enero de 2012 a las 20:04

  • ¿Cómo es ese un comentario constructivo?

    – Louth

    3 de febrero de 2017 a las 2:00

  • Los creadores de Java pueden introducir una nueva palabra clave: no instancia de. Solo mis dos centavos ^^

    – Stephan

    13 de marzo de 2018 a las 17:19


No, no hay mejor manera; el tuyo es canónico.

  • En realidad, puede ser como: if (!(obj instanceof String)) – ¡Funciona bien!

    – arun

    26 de mayo a las 10:51

  • @arun Esa es la sintaxis que todos odiamos, y el cartel original pregunta cómo evitar.

    – Ian Boyd

    19 de julio a las 19:27

avatar de usuario
natix

No sé qué imaginas cuando dices “hermoso”, pero ¿y esto? Personalmente, creo que es peor que la forma clásica que publicaste, pero a alguien le podría gustar…

if (str instanceof String == false) { /* ... */ }

  • Sobre la doble lógica, podrías usar != true en vez de == false 😀

    – jupi

    16 de noviembre de 2018 a las 14:27

  • Ver esto me ayuda a entender que if(!(str instanceof String)) es la única manera correcta, y necesito dejar de pensar en alternativas

    – Vikash

    11 de mayo de 2019 a las 7:31


  • ¡Me gusta esta solución ya que no estoy obligado a construir una pila de metal mientras la leo!

    – Mermelada

    9 de agosto de 2019 a las 12:59

  • SonarLint informará un problema sobre este formulario de codificación (como Code Smell menor), cuyo mensaje es: Eliminar el valor booleano literal “falso”.

    – Ray Chen

    4 de diciembre de 2020 a las 10:43

  • los verificadores de código estático se quejan de esto, pero prefiero esto, ese pequeño ! el carácter es tan fácil de pasar por alto… Y yo diría que hay muchos “nosotros”, por ejemplo, StringUtils ofrece ambos isBlank() y isNotBlank() comparado con !isBlank()

    – Betlista

    14 de enero a las 14:12


avatar de usuario
Dacwe

Podrías usar el Class.isInstance método:

if(!String.class.isInstance(str)) { /* do Something */ }

… pero todavía es negado y bastante feo.

  • es un poco mejor, el exceso de paréntesis hace que el código sea feo, en mi humilde opinión.

    – caarlos0

    30 de enero de 2012 a las 18:02

  • ¿No es esto mucho más lento?

    – maxammann

    02/08/2013 a las 20:54

  • Esto tiene un comportamiento diferente. La palabra clave instanceof incluye subclases, el método no, necesita usar Class.isAssignableFrom para replicar el comportamiento.

    – Chris Cooper

    4 de febrero de 2014 a las 17:11

  • @ChrisCooper Esto no es cierto: this method returns true if the specified Object argument is an instance of the represented class (or of any of its subclasses)

    – Natix

    19 de agosto de 2014 a las 14:51

avatar de usuario
pedro laurey

Por lo general, no desea solo un if pero un else cláusula también.

if(!(str instanceof String)) { /* do Something */ } 
else { /* do something else */ }

Se puede escribir como

if(str instanceof String) { /* do Something else */ } 
else { /* do something */ }

O puede escribir el código para que no necesite saber si es una cadena o no. p.ej

if(!(str instanceof String)) { str = str.toString(); } 

Se puede escribir como

str = str.toString();

Si puede usar importaciones estáticas y su código moral lo permite

public class ObjectUtils {
    private final Object obj;
    private ObjectUtils(Object obj) {
        this.obj = obj;
    }

    public static ObjectUtils thisObj(Object obj){
        return new ObjectUtils(obj);
    }

    public boolean isNotA(Class<?> clazz){
        return !clazz.isInstance(obj);
    }
}

Y entonces…

import static notinstanceof.ObjectUtils.*;

public class Main {

    public static void main(String[] args) {
        String a = "";
        if (thisObj(a).isNotA(String.class)) {
            System.out.println("It is not a String");
        }
        if (thisObj(a).isNotA(Integer.class)) {
            System.out.println("It is not an Integer");
        }
    }    
}

Este es solo un ejercicio de interfaz fluida, ¡nunca lo usaría en el código de la vida real!
Elija su forma clásica, ¡no confundirá a nadie más que lea su código!

  • No me gustan las importaciones estáticas … de todos modos, gracias por intentar ayudar 🙂

    – caarlos0

    30 de enero de 2012 a las 19:19

Si lo encuentra más comprensible, puede hacer algo como esto con Java 8:

public static final Predicate<Object> isInstanceOfTheClass = 
    objectToTest -> objectToTest instanceof TheClass;

public static final Predicate<Object> isNotInstanceOfTheClass = 
    isInstanceOfTheClass.negate(); // or objectToTest -> !(objectToTest instanceof TheClass)

if (isNotInstanceOfTheClass.test(myObject)) {
    // do something
}

  • No me gustan las importaciones estáticas … de todos modos, gracias por intentar ayudar 🙂

    – caarlos0

    30 de enero de 2012 a las 19:19

ok, solo mis dos centavos, use un método de cadena is:

public static boolean isString(Object thing) {
    return thing instanceof String;
}

public void someMethod(Object thing){
    if (!isString(thing)) {
        return null;
    }
    log.debug("my thing is valid");
}

¿Ha sido útil esta solución?