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.