Der beste Weg, um eine Instanz von zu "negieren"

408

Ich dachte, ob es einen besseren / schöneren Weg gibt, einen instanceofin Java zu negieren . Eigentlich mache ich so etwas wie:

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

Aber ich denke, dass eine "schöne" Syntax dafür existieren sollte.

Weiß jemand, ob es existiert und wie die Syntax aussieht?


EDIT: Mit schön könnte ich so etwas sagen:

if(str !instanceof String) { /* do Something */ } // compilation fails
caarlos0
quelle
24
Ich hasse die Vorrangregeln für instanceofso viel ...
luiscubal
4
Sie könnten immer eine Variable erstellen, so etwas wie boolean strIsString = str instanceof String;...
Vaughandroid
Ja, @Baqueta, ist eine Option. Aber welche Unterschiede können bei der Speichernutzung in der einen oder anderen Syntax auftreten?
Caarlos0
2
Wie ist das ein konstruktiver Kommentar?
Louth
2
Die Java-Ersteller können ein neues Schlüsselwort einführen : notinstanceof . Nur meine zwei Cent ^^
Stephan

Antworten:

307

Nein, es gibt keinen besseren Weg. deins ist kanonisch.

Maerics
quelle
131

Ich weiß nicht, was Sie sich vorstellen, wenn Sie "schön" sagen, aber was ist damit? Ich persönlich denke, es ist schlimmer als das klassische Formular, das Sie gepostet haben, aber es könnte jemandem gefallen ...

if (str instanceof String == false) { /* ... */ }
Natix
quelle
2
Über doppelte Logik könnten Sie != trueanstelle von == false: D
jupi
Wenn ich das sehe, kann ich verstehen, dass dies if(!(str instanceof String)) der einzig richtige Weg ist, und ich muss aufhören, über Alternativen nachzudenken
Vikash,
Ich mag diese Lösung, da ich beim Lesen keinen Metallstapel aufbauen muss!
JaM
59

Sie könnten die Class.isInstanceMethode verwenden:

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

... aber es ist immer noch negiert und ziemlich hässlich.

Dacwe
quelle
5
ist ein bisschen besser, die überschüssige Klammer macht den Code hässlich, IMHO.
Caarlos0
Ist das nicht viel langsamer?
Maxammann
4
Dies hat ein anderes Verhalten. Das Schlüsselwort instanceof enthält Unterklassen, die Methode nicht. Sie müssen Class.isAssignableFrom verwenden, um das Verhalten zu replizieren.
Chris Cooper
7
@ ChrisCooper Dies ist nicht wahr:this method returns true if the specified Object argument is an instance of the represented class (or of any of its subclasses)
Natix
24

Normalerweise möchten Sie nicht nur eine, ifsondern auch eine elseKlausel.

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

kann geschrieben werden als

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

Oder Sie können den Code schreiben, damit Sie nicht wissen müssen, ob es sich um einen String handelt oder nicht. z.B

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

kann geschrieben werden als

str = str.toString();
Peter Lawrey
quelle
12

Wenn Sie statische Importe verwenden können und Ihr Moralkodex dies zulässt

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

Und dann...

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

Dies ist nur eine fließende Interface-Übung, die ich im realen Code niemals verwenden würde!
Gehen Sie Ihren klassischen Weg, es wird niemanden verwirren, der Ihren Code liest!

Pablo Grisafi
quelle
Ich mag keine statischen Importe .. trotzdem danke für den Versuch zu helfen :)
caarlos0
4

Wenn Sie es verständlicher finden, können Sie mit Java 8 Folgendes tun:

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
}
Paul
quelle
1
Mit Java 11 sollte dies funktionieren if (Predicate.not(isInstanceOfTheClass).test(myObject)) { .... Nicht besser, imo, sollte aber funktionieren!
Patrick M
3

ok nur meine zwei Cent, benutze eine is string Methode:

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
quelle
0

Sie können dies erreichen, indem Sie die folgenden Schritte ausführen. Fügen Sie einfach eine Bedingung hinzu, indem Sie eine Klammer if(!(condition with instanceOf))mit der gesamten Bedingung hinzufügen, indem Sie !am Anfang den Operator hinzufügen, wie in den folgenden Codeausschnitten beschrieben.

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

anstatt

if(str !instanceof String) { /* do Something */ } // COMPILATION FAIL
Dharmesh Baldha
quelle
0

Ich bin damit einverstanden, dass dies in den meisten Fällen der if (!(x instanceof Y)) {...}beste Ansatz ist, aber in einigen Fällen lohnt es sich , eine isY(x)Funktion zu erstellen , damit Sie dies können if (!isY(x)) {...}.

Ich bin ein Typoskript-Neuling und bin in den letzten Wochen einige Male auf diese S / O-Frage gestoßen. Für die Googler besteht die Typoskript-Methode darin, einen Typeguard wie den folgenden zu erstellen:

typeGuards.ts

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

Verwendungszweck

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

Ich denke, der einzige Grund, warum dies in Typoskript und nicht in regulärem js angemessen sein könnte, ist, dass Typeguards eine gängige Konvention sind. Wenn Sie sie also für andere Schnittstellen schreiben, ist es vernünftig / verständlich / natürlich, sie auch für Klassen zu schreiben.

Weitere Informationen zu benutzerdefinierten Typschutzvorrichtungen wie diesen finden Sie in den Dokumenten

Mr5o1
quelle