Il modo migliore per "annullare" un'istanza di


409

Stavo pensando se esiste un modo migliore / migliore per negare un instanceofin Java. In realtà, sto facendo qualcosa del tipo:

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

Ma penso che dovrebbe esistere una "bella" sintassi per farlo.

Qualcuno sa se esiste e come appare la sintassi?


EDIT: Per bello, potrei dire qualcosa del genere:

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

24
Odio le regole di precedenza per instanceofcosì tanto ...
luiscubal

4
Puoi sempre creare una variabile, qualcosa come boolean strIsString = str instanceof String;...
vaughandroid

sì, @ Baqueta, è un'opzione. Ma quali differenze potrebbero verificarsi nell'uso della memoria in una sintassi o in un'altra?
caarlos0,

2
Come è un commento costruttivo?
Louth,

2
I creatori di Java possono introdurre una nuova parola chiave: notinstanceof . Solo i miei due centesimi ^^
Stephan,

Risposte:


308

No, non esiste un modo migliore; il tuo è canonico.


132

Non so cosa immagini quando dici "bello", ma che dire di questo? Personalmente penso che sia peggio della forma classica che hai pubblicato, ma a qualcuno potrebbe piacere ...

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

2
A proposito di doppia logica, è possibile utilizzare != trueinvece di == false: D
jupi

Vedere questo mi aiuta a capire che if(!(str instanceof String)) è l'unico modo giusto, e ho bisogno di smettere di pensare alle alternative
Vikash,

Mi piace questa soluzione poiché non mi viene richiesto di creare una pila di metallo durante la lettura!
JaM

60

È possibile utilizzare il Class.isInstancemetodo:

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

... ma è ancora negato e piuttosto brutto.


5
è un po 'meglio, la parentesi in eccesso rende il codice brutto, IMHO.
caarlos0,

Non è molto più lento?
maxammann,

4
Questo ha un comportamento diverso. La parola chiave instanceof include sottoclassi, il metodo no, è necessario utilizzare Class.isAssignableFrom per replicare il comportamento.
Chris Cooper,

7
@ChrisCooper Questo non è vero:this method returns true if the specified Object argument is an instance of the represented class (or of any of its subclasses)
Natix

24

Di solito non vuoi solo una ifma anche una elseclausola.

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

può essere scritto come

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

Oppure puoi scrivere il codice in modo da non dover sapere se è una stringa o no. per esempio

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

può essere scritto come

str = str.toString();

12

Se puoi usare le importazioni statiche e il tuo codice morale le consente

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

E poi...

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

Questo è solo un esercizio di interfaccia fluente, non lo userei mai nel codice della vita reale!
Scegli il tuo modo classico, non confonderà nessun altro che legge il tuo codice!


Non mi piacciono le importazioni statiche .. grazie comunque per aver cercato di aiutare :)
caarlos0

4

Se lo trovi più comprensibile, puoi fare qualcosa del genere 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, questo dovrebbe funzionare if (Predicate.not(isInstanceOfTheClass).test(myObject)) { .... Non meglio, imo, ma dovrebbe funzionare!
Patrick M,

3

ok solo i miei due centesimi, utilizzare un metodo 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

Puoi ottenere facendo in questo modo .. basta aggiungere una condizione aggiungendo parentesi if(!(condition with instanceOf))con l'intera condizione aggiungendo !operatore all'inizio proprio come indicato negli snippet di codice seguenti.

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

invece di

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

0

Concordo sul fatto che nella maggior parte dei casi if (!(x instanceof Y)) {...}è l'approccio migliore, ma in alcuni casi è utile creare una isY(x)funzione in modo che sia possibile if (!isY(x)) {...}.

Sono un novizio dattiloscritto e ho incontrato questa domanda S / O un sacco di volte nelle ultime settimane, quindi per i googler il modo dattiloscritto per farlo è quello di creare una macchina da scrivere come questa:

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

Immagino che l'unica ragione per cui questo potrebbe essere appropriato in dattiloscritto e non nei normali js è che i typeguards sono una convenzione comune, quindi se li scrivi per altre interfacce, è ragionevole / comprensibile / naturale scriverli anche per le classi.

Ci sono maggiori dettagli sulle protezioni dei tipi definite dall'utente come questa nei documenti

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.