Is null check needed before calling instanceof?
Asked Answered
D

8

1612

Will null instanceof SomeClass return false or throw a NullPointerException?

Derogative answered 1/6, 2010 at 13:53 Comment(3)
It's also 'important' or at least very useful as a 'best-practise' starting(or very early) line for for any Compare or Equals or similar method that is designed to only succeed on non-null objects of the same type, and guards you against the 'silly cases' in a single line. less code = less bugs.Reclusion
To weigh in on the "is this useful?" debate - I've never written my own Java code (so don't easily know where the specs are, and compiling a test would be very non-trivial), but I'm currently manually converting Java to JavaScript. My code was failing on a null reference, and googling this let me see the accepted answer, which confirmed that it was expected behavior and that I was missing an implicit null check. Very useful, in my case.Turman
I have leveraged the fact that instanceof checks for null to implement a very tight Java equals() implementation that reads way cleaner than those I see auto-generated by Eclipse and IntelliJ: https://mcmap.net/q/46055/-implementation-equals-method-design-patternCounterintelligence
E
2183

No, a null check is not needed before using instanceof.

The expression x instanceof SomeClass is false if x is null.

The Java 11 Language Specification expresses this concisely in section 15.20.2, "Type comparison operator instanceof". (Java 17 expresses this less concisely, after the introduction of instanceof pattern matching.)

"At run time, the result of the instanceof operator is true if the value of the RelationalExpression is not null and the reference could be cast to the ReferenceType without raising a ClassCastException. Otherwise the result is false."

So if the operand is null, the result is false.

Emplace answered 1/6, 2010 at 14:5 Comment(11)
This answer is more correct than try it because current behavior is not the same as guaranteed behavior.Rios
This question comes into play during Joshua Bloch's chapter on object equality in Effective Java - amazon.com/Effective-Java-Edition-Joshua-Bloch/dp/0321356683Stepha
Specifically, in Item 8, he notes that in equals() methods, one instanceof operator serves two purposes - it verifies that the argument is both non-null and of the correct type. "...[S]o you don't need a separate null check."Emplace
I don't see them ever changing this. It can only return true or false so how can can it ever be true for a null reference to be an instanceof anything?Indiscriminate
@BenThurley - Java's instanceof operator was part of Java 1.0, released almost 20 years ago. Changing the behavior now in a way that would break existing code is unlikely, absent some benefit that outweighs that huge cost. Twenty years ago, maybe there could have been arguments for returning true iff the argument could be cast, or throwing an exception for a null argument. But those definitions would have required separate null checks.Emplace
Exactly my point. It's true that current behaviour is not the same as guaranteed behaviour but in this case I think it's pretty well guaranteed.Indiscriminate
@BenThurley - The behavior is guaranteed by Java specifications past and present. I think Luke's point addresses the limitations of experimentation in determining the guaranteed behavior of the present.Emplace
Why the compiler let you do this: "null instance of Class" lol. I mean, if it is a hardcoded null, it doesn't make sense to even ask itTonitonia
@Tonitonia that’s like writing with a red pen on a red paper. Even if it makes no sense, it’s possible due to the general possibility to combine an arbitrary pen with an arbitrary paper. And implementing a “writing on the same color” check into a pen would complicate the technology for little to no benefit.Seely
@Tonitonia meanwhile, also a great help in avoiding NPE, for example when you do if (myObj instance of SomeClass)Macneil
Interestingly, this is the major way instanceof differs from a typecast. When v is null, v instanceof C is false, while (C)v throws a ClassCastException. docs.oracle.com/javase/specs/jvms/se19/html/…Repress
F
322

Using a null reference as the first operand to instanceof returns false.

Flavorous answered 1/6, 2010 at 13:53 Comment(5)
(And now it takes 10 seconds to find this question in Google)Dresden
While using !null as the first operand to instanceof also returns false. Fun!Fulvi
@Fulvi that would be a syntax error, need to use parentheses.Madera
It's valid syntax, just confusing. !null is truthy.Fulvi
@Fulvi Note that the question was about Java and not JavaScript or other languages with concepts like "truthy"Subir
C
86

Very good question indeed. I just tried for myself.

public class IsInstanceOfTest {

    public static void main(final String[] args) {

        String s;

        s = "";

        System.out.println((s instanceof String));
        System.out.println(String.class.isInstance(s));

        s = null;

        System.out.println((s instanceof String));
        System.out.println(String.class.isInstance(s));
    }
}

Prints

true
true
false
false

JLS / 15.20.2. Type Comparison Operator instanceof

At run time, the result of the instanceof operator is true if the value of the RelationalExpression is not null and the reference could be cast to the ReferenceType without raising a ClassCastException. Otherwise the result is false.

API / Class#isInstance(Object)

If this Class object represents an interface, this method returns true if the class or any superclass of the specified Object argument implements this interface; it returns false otherwise. If this Class object represents a primitive type, this method returns false.

Convection answered 29/7, 2013 at 11:55 Comment(8)
Kind of confusing. s is a String because it says "String s", s is not a String because it is null. So what the hell is s?Workout
@KaiWang s is just an object reference variable. It may refer an actually existing object("") or it may refer a(the) null literal reference.Convection
I'm still confused. s might be null now, but it can only be pointed to a String instance later. It can not be pointed to, like, an Integer. So it is still kind of a String, even it is a null. Just doesn't make much sense...Workout
@KaiWang You are confusing the variable type with the type of the actual object. Variables aren't instances; they're effectively just pointers. null isn't string data, no matter what variable is pointing to it. s instanceof String is not the same as field.getType().equals(String.class), for example.Gilbertson
@KaiWang you have to imagine that in the call s instanceof String the s gets replaced with the actual value, so that would become "" instanceof String and null instanceof String. Thinking about it like this may make more sense.Inga
@KaiWang The instanceof operator checks if a value is an instance of a certain type, not if a value is assignable as (castable to) a certain type. null is not an instance of any type, but it can still be assigned to a variable of any type. This is why instanceof always returns false for null, but any reference variable of an object type can hold a value of null.Sanctified
@Kröw, "not an instance of any type"? Be careful there with "instance". null "is of the null type" (Java Language Specification for se8, section 3.10.7) AND section 4.1: "There is also a special null type, the type of the expression null (§3.10.7, §15.8.1), which has no name." You can look further into the SE8 JLS if you like hereAnachronism
@KaiWang you're right, it really is confusing. This is why null is often considered to be a hole in the type system. It makes a little more sense if you focus on the "instance" part of instanceof: null is not an instance of anything.Dehypnotize
P
28

No, it's not. instanceof would return false if its first operand is null.

Perky answered 1/6, 2010 at 13:53 Comment(0)
L
26

Just as a tidbit:

Even (((A)null)instanceof A) will return false.


(If typecasting null seems surprising, sometimes you have to do it, for example in situations like this:

public class Test
{
  public static void test(A a)
  {
    System.out.println("a instanceof A: " + (a instanceof A));
  }

  public static void test(B b) {
    // Overloaded version. Would cause reference ambiguity (compile error)
    // if Test.test(null) was called without casting.
    // So you need to call Test.test((A)null) or Test.test((B)null).
  }
}

So Test.test((A)null) will print a instanceof A: false.)


P.S.: If you are hiring, please don't use this as a job interview question. :D

Labaw answered 22/3, 2018 at 12:11 Comment(1)
Regarding your PS: If someone is actually supplying gotcha questions in an interview, they are too junior to be interviewing. The right or wrong answer to any question should never matter in an interview. It's the ensuing conversation around the topic that matters.Anachronism
M
6

No, a null check is not needed before calling instanceof. It always returns false if its value is null.

As per Java Language Specification for comparison using instanceof.

At run time, the result of the instanceof operator is true if the value of the RelationalExpression is not null and the reference could be cast to the ReferenceType without raising a ClassCastException. Otherwise the result is false

Hence we can infer that java has something called null type also, and this null type is checked in instanceof operator which obviously returns false because it is expecting a specific type.

There are two kinds of types in the Java programming language: primitive types and reference types. As per Java Specification on types and value

There is also a special null type, the type of the expression null, which has no name. Because the null type has no name, it is impossible to declare a variable of the null type or to cast to the null type. The null reference is the only possible value of an expression of null type. The null reference can always undergo a widening reference conversion to any reference type.

From Java 14 onwards and esp. in LTS Java 17 we have an enhanced instanceof. We have pattern matching feature which performs casts after type comparisons.

Example

public static void main(String[] args) {
    Object testObject = "I am a string";
    List<Object> testList = null;
    if (testList instanceof List) {
        System.out.println("instance of list");
    } else {
        System.out.println("null type");
    }
    //Enhanced instanceof with type conversion - tested with JDK 17
    if (testObject instanceof String str) {
        System.out.println(str.toUpperCase());
    }
}

Output

null type
I AM A STRING
Magnanimity answered 26/1, 2022 at 8:41 Comment(0)
X
3
  • null check is not needed before instanceof
  • null check is not needed after instanceof that validates to true

The following are null-safe:

if(couldbenull instanceof Comparable comp){
   return comp.compareTo(somethingElse);
}
//java < 14
if(couldbenull instanceof Comparable){
   return ((Comparable)couldbenull).compareTo(somethingElse);
}
Xylo answered 7/4, 2021 at 15:57 Comment(0)
C
2

The instanceof operator does not need explicit null checks, as it does not throw a NullPointerException if the operand is null.

At run time, the result of the instanceof operator is true if the value of the relational expression is not null and the reference could be cast to the reference type without raising a class cast exception.

If the operand is null, the instanceof operator returns false and hence, explicit null checks are not required.

Consider the below example,

public static void main(String[] args) {
         if(lista != null && lista instanceof ArrayList) {                     //Violation
                System.out.println("In if block");
         }
         else {
                System.out.println("In else block");
         }
}

The correct usage of instanceof is as shown below,

public static void main(String[] args) {
      
         if(lista instanceof ArrayList){                     //Correct way
                  System.out.println("In if block");
         }
            else {
                 System.out.println("In else block");
         }  
}
Coroneted answered 1/4, 2015 at 8:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.