Najlepszy sposób na „zanegowanie” instancji

409

Myślałem, czy istnieje lepszy / ładniejszy sposób na zanegowanie instanceofw Javie. Właściwie robię coś takiego:

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

Uważam jednak, że powinna istnieć „piękna” składnia do tego celu.

Czy ktoś wie, czy istnieje i jak wygląda składnia?


EDYCJA: Pięknie, mogę powiedzieć coś takiego:

if(str !instanceof String) { /* do Something */ } // compilation fails
caarlos0
źródło
24
Tak bardzo nienawidzę zasad pierwszeństwa instanceof...
luiscubal
4
Zawsze możesz utworzyć zmienną, coś w stylu boolean strIsString = str instanceof String;...
vaughandroid
tak, Baqueta, jest opcją. Ale jakie różnice mogą się zdarzyć w użyciu pamięci w takiej czy innej składni?
caarlos0
2
Jak to jest konstruktywny komentarz?
Louth
2
Twórcy Java mogą wprowadzić nowe słowo kluczowe: notinstanceof . Tylko moje dwa centy ^^
Stephan

Odpowiedzi:

308

Nie, nie ma lepszego sposobu; twój jest kanoniczny.

maerika
źródło
132

Nie wiem, co sobie wyobrażasz, kiedy mówisz „piękny”, ale co z tym? Osobiście uważam, że jest gorzej niż klasyczna forma, którą opublikowałeś, ale ktoś może się spodobać ...

if (str instanceof String == false) { /* ... */ }
Natix
źródło
2
O podwójnej logice możesz użyć != truezamiast == false: D
jupi
Widząc to, pomaga mi zrozumieć, że if(!(str instanceof String)) jest to jedyny właściwy sposób, i muszę przestać myśleć o alternatywach
Vikash,
Podoba mi się to rozwiązanie, ponieważ nie muszę odkładać metalowego stosu podczas czytania!
JaM,
59

Możesz użyć Class.isInstancemetody:

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

... ale wciąż jest negowane i dość brzydkie.

dacwe
źródło
5
jest trochę lepszy, nadmiar nawiasu powoduje, że kod jest brzydki, IMHO.
caarlos0
Czy to nie jest dużo wolniejsze?
maxammann
4
To ma inne zachowanie. Słowo kluczowe instanceof zawiera podklasy, metoda nie, musisz użyć Class.isAssignableFrom, aby zreplikować zachowanie.
Chris Cooper
7
@ChrisCooper To nie jest prawda:this method returns true if the specified Object argument is an instance of the represented class (or of any of its subclasses)
Natix
24

Zwykle nie chcesz po prostu ifale elseklauzula, jak również.

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

można zapisać jako

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

Możesz też napisać kod, aby nie trzeba było wiedzieć, czy jest to ciąg znaków, czy nie. na przykład

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

można zapisać jako

str = str.toString();
Peter Lawrey
źródło
12

Jeśli możesz użyć importu statycznego, a twój kodeks moralny na to pozwala

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

I wtedy...

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

To tylko płynne ćwiczenie interfejsu, nigdy nie użyłbym tego w prawdziwym kodzie!
Idź swoją klasyczną drogą, nie pomyli to nikogo, kto czyta Twój kod!

Pablo Grisafi
źródło
Nie podoba mi się import statyczny .. zresztą dzięki za próbę pomocy :)
caarlos0
4

Jeśli uznasz to za bardziej zrozumiałe, możesz zrobić coś takiego z Javą 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
}
Paweł
źródło
1
W przypadku Java 11 powinno to działać if (Predicate.not(isInstanceOfTheClass).test(myObject)) { .... Nie lepiej, imo, ale powinno działać!
Patrick M,
3

ok tylko moje dwa centy, użyj metody 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
źródło
0

Możesz to zrobić, wykonując poniższy sposób. Po prostu dodaj warunek, dodając nawias if(!(condition with instanceOf))do całego warunku, dodając !operator na początku w sposób opisany w poniższych fragmentach kodu.

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

zamiast

if(str !instanceof String) { /* do Something */ } // COMPILATION FAIL
Dharmesh Baldha
źródło
0

Zgadzam się, że w większości przypadków if (!(x instanceof Y)) {...}jest to najlepsze podejście, ale w niektórych przypadkach warto utworzyć isY(x)funkcję, abyś mógł if (!isY(x)) {...}to zrobić .

Jestem nowicjuszką maszynopisu i wpadłem na to pytanie kilka razy w ciągu ostatnich kilku tygodni, więc dla googlersów sposobem na zrobienie tego jest utworzenie takiego maszynopisarki:

typeGuards.ts

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

stosowanie

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

Wydaje mi się, że jedynym powodem, dla którego może to być odpowiednie w maszynopisie, a nie w zwykłym js, jest fakt, że typguardy są powszechną konwencją, więc jeśli piszesz je dla innych interfejsów, rozsądne / zrozumiałe / naturalne jest pisanie ich również dla klas.

Jest więcej szczegółów o zdefiniowane przez użytkownika strażników typu jak ten w docs

Mr5o1
źródło