La mejor manera de "negar" una instancia de


409

Estaba pensando si existe una manera mejor / mejor de negar un instanceofen Java. En realidad, estoy haciendo algo como:

if(!(str instanceof String)) { /* 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 hermosa, podría decir algo como esto:

if(str !instanceof String) { /* do Something */ } // compilation fails

24
Odio las reglas de precedencia por instanceoftanto ...
luiscubal

44
Siempre se puede crear una variable, algo así como boolean strIsString = str instanceof String;...
vaughandroid

Sí @Baqueta, es una opción. Pero, ¿qué diferencias pueden ocurrir en el uso de la memoria en una sintaxis u otra?
caarlos0

2
¿Cómo es eso un comentario constructivo?
Louth

2
Los creadores de Java pueden introducir una nueva palabra clave: notinstanceof . Solo mis dos centavos ^^
Stephan

Respuestas:



132

No sé qué imaginas cuando dices "hermoso", pero ¿qué pasa con esto? Personalmente, creo que es peor que el formulario clásico que publicaste, pero a alguien podría gustarle ...

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

2
Acerca de la lógica doble, podría usar en != truelugar de == false: D
jupi

Ver esto me ayuda a comprender que esa if(!(str instanceof String)) es la única forma correcta, y necesito dejar de pensar en alternativas
Vikash,

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

60

Podrías usar el Class.isInstancemétodo:

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

... pero todavía está negado y es bastante feo.


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

¿No es esto mucho más lento?
maxammann

44
Esto tiene un comportamiento diferente. La palabra clave instanceof incluye subclases, el método no, debe usar Class.isAssignableFrom para replicar el comportamiento.
Chris Cooper

77
@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

24

Por lo general, no solo quieres ifuna elsecláusula sino también una .

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();

12

Si puede usar importaciones estáticas, y su código moral les 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 fluido, ¡nunca lo usaría en el código de la vida real!
Vaya por su camino clásico, ¡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

4

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
}

1
Con Java 11, esto debería funcionar if (Predicate.not(isInstanceOfTheClass).test(myObject)) { .... No mejor, OMI, pero debería funcionar!
Patrick M

3

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

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");
}

0

Puede lograrlo haciendo lo siguiente: solo agregue una condición agregando un corchete if(!(condition with instanceOf))con toda la condición agregando el !operador al inicio de la manera mencionada en los fragmentos de código a continuación.

if(!(str instanceof String)) { /* do Something */ } // COMPILATION WORK

en vez de

if(str !instanceof String) { /* do Something */ } // COMPILATION FAIL

0

Estoy de acuerdo en que, en la mayoría de los casos, este if (!(x instanceof Y)) {...}es el mejor enfoque, pero en algunos casos crear unisY(x) función para que puedaif (!isY(x)) {...} vale la pena .

Soy un novato en mecanografía, y me he topado con esta pregunta de S / O varias veces en las últimas semanas, por lo que para los googlers, la forma de mecanografiar esto es crear una protección de letra como esta:

typeGuards.ts

export function isHTMLInputElement (value: any): value is HTMLInputElement {
  return value instanceof HTMLInputElement
}

uso

if (!isHTMLInputElement(x)) throw new RangeError()
// do something with an HTMLInputElement

Supongo que la única razón por la que esto podría ser apropiado en mecanografiado y no js regular es que los protectores de tipografía son una convención común, por lo que si los escribe para otras interfaces, es razonable / comprensible / natural escribirlos también para las clases.

Hay más detalles sobre los protectores de tipo definidos por el usuario como este en los documentos

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.