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

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:



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

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.


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

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!


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
}

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

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

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

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.