caarlos0
caarlos0

Reputation: 20633

Best way to "negate" an instanceof

I was thinking if there exists a better/nicer way to negate an instanceof in Java. Actually, I'm doing something like:

if(!(myObject instanceof SomeClass)) { /* do Something */ }

But I think that a "beautiful" syntax to do this should exist.

Does anyone know if it exists, and how the syntax look like?


EDIT: By beautiful, I might say something like this:

if(myObject !instanceof SomeClass) { /* do Something */ } // compilation fails

Upvotes: 564

Views: 271918

Answers (9)

Mr5o1
Mr5o1

Reputation: 1828

I agree that in most cases the if (!(x instanceof Y)) {...} is the best approach, but in some cases creating an isY(x) function so you can if (!isY(x)) {...} is worthwhile.

I'm a typescript novice, and I've bumped into this S/O question a bunch of times over the last few weeks, so for the googlers the typescript way to do this is to create a typeguard like this:

typeGuards.ts

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

usage

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

I guess the only reason why this might be appropriate in typescript and not regular js is that typeguards are a common convention, so if you're writing them for other interfaces, it's reasonable / understandable / natural to write them for classes too.

There's more detail about user defined type guards like this in the docs

Upvotes: 1

Dharmesh Baldha
Dharmesh Baldha

Reputation: 816

You can achieve by doing below way.. just add a condition by adding bracket if(!(condition with instanceOf)) with the whole condition by adding ! operator at the start just the way mentioned in below code snippets.

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

instead of

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

Upvotes: -1

Paul
Paul

Reputation: 1041

If you find it more understandable, you can do something like this with 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
}

Upvotes: 6

tibi
tibi

Reputation: 677

ok just my two cents, use a is string method:

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

Upvotes: 3

Natix
Natix

Reputation: 14247

I don't know what you imagine when you say "beautiful", but what about this? I personally think it's worse than the classic form you posted, but somebody might like it...

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

Upvotes: 171

Peter Lawrey
Peter Lawrey

Reputation: 533432

Usually you don't want just an if but an else clause as well.

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

can be written as

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

Or you can write the code so you don't need to know if its a String or not. e.g.

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

can be written as

str = str.toString();

Upvotes: 34

Pablo Grisafi
Pablo Grisafi

Reputation: 5047

If you can use static imports, and your moral code allows them

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

And then...

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

This is just a fluent interface exercise, I'd never use that in real life code!
Go for your classic way, it won't confuse anyone else reading your code!

Upvotes: 13

dacwe
dacwe

Reputation: 43504

You could use the Class.isInstance method:

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

... but it is still negated and pretty ugly.

Upvotes: 66

maerics
maerics

Reputation: 156364

No, there is no better way; yours is canonical.

Upvotes: 412

Related Questions