532

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
Stephan
  • 41,764
  • 65
  • 238
  • 329
caarlos0
  • 20,020
  • 27
  • 85
  • 160

9 Answers9

392

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

maerics
  • 151,642
  • 46
  • 269
  • 291
163

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) { /* ... */ }
ThomasW
  • 16,981
  • 4
  • 79
  • 106
Natix
  • 14,017
  • 7
  • 54
  • 69
  • 5
    About double logic, you could use `!= true` instead of `== false` :D – jupi Nov 16 '18 at 14:27
  • 4
    Seeing this helps me to understand that `if(!(str instanceof String))` is the only right way, and I need to stop thinking alternatives – Vikash May 11 '19 at 07:31
  • I like this solution since I am not required to build up a metal stack while reading it! – JaM Aug 09 '19 at 12:59
  • SonarLint will report an issue about this coding form (as a minor Code Smell), which message is: Remove the literal "false" boolean value. – Ray Chen Dec 04 '20 at 10:43
  • static code checkers complain about this, but I prefer this, that small `!` character is so easy to overlook... And I'd say there is a lot of "us", e.g. StringUtils offers both `isBlank()` and `isNotBlank()` compared to `!isBlank()`... – Betlista Jan 14 '22 at 14:12
  • Actually there can be like: if (!(obj instanceof String)) - Works just fine! – arun May 26 '22 at 10:51
65

You could use the Class.isInstance method:

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

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

dacwe
  • 43,066
  • 12
  • 116
  • 140
  • 5
    is a little bit better, the excess parenthesis makes the code ugly, IMHO. – caarlos0 Jan 30 '12 at 18:02
  • 1
    Isn't this a lot of slower? – maxammann Aug 02 '13 at 20:54
  • 4
    This has different behaviour. The instanceof keyword includes subclasses, the method does not, you need to use Class.isAssignableFrom to replicate the behaviour. – Chris Cooper Feb 04 '14 at 17:11
  • 9
    @ChrisCooper This is not true: `this method returns true if the specified Object argument is an instance of the represented class (or of any of its subclasses)` – Natix Aug 19 '14 at 14:51
32

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();
Koray Tugay
  • 22,894
  • 45
  • 188
  • 319
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • I think this is the best answer here(first part) – Jawad El Fou Oct 16 '20 at 14:57
  • This must be an acceptable answer as IntelliJ also suggested this method. – Udhaya Jun 07 '21 at 06:24
  • This might just be a "me" problem, but if not and others are in a similar situation, I wanted to at least add the comment that my first reading of the first part was "most of the time it's good practice to always include an `else` for your `if`, even if it's just a no-op", which I'd call bad advice. I now realize I misread that, but wanted to drop this note in case anyone else misreads it as well. Great answer! – acat Feb 04 '22 at 05:58
13

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!

Pablo Grisafi
  • 5,039
  • 1
  • 19
  • 29
6

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
}
Paul
  • 1,410
  • 1
  • 14
  • 30
  • 1
    With Java 11, this should work `if (Predicate.not(isInstanceOfTheClass).test(myObject)) { ...`. Not better, imo, but should work! – Patrick M Dec 04 '19 at 21:14
3

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");
}
tibi
  • 657
  • 1
  • 10
  • 22
1

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
Dharmesh Baldha
  • 820
  • 6
  • 11
1

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

Mr5o1
  • 1,698
  • 1
  • 15
  • 20