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
caarlos0
fuente
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:

308

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

maerics
fuente
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) { /* ... */ }
Natix
fuente
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.

dacwe
fuente
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();
Peter Lawrey
fuente
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!

Pablo Grisafi
fuente
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
}
Pablo
fuente
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");
}
tibi
fuente
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
Dharmesh Baldha
fuente
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

Mr5o1
fuente