Is null check needed before calling instanceof?
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 patternmatching.)
"At run time, the result of the
instanceof
operator istrue
if the
value of the RelationalExpression is
notnull
and the reference could be
cast to the ReferenceType
without raising aClassCastException
.
Otherwise the result isfalse
."
So if the operand is null, the result is false.
Why or why not use instanceof to check if not null
That depends on what you are actually checking
If you just want to know whether the reference is
null
, usex == null
and nothing elseIf you want to know whether a particular reference is not
null
and points to an instance of typeFoo
you may usex instanceof Foo
as it implies being notnull
But if the compile-time type of the reference is already
Foo
, you know that the instance is of typeFoo
when it is non-null
, therefore the first bullet applies in this case; you just want to test fornull
. This is the case in your updated question’s example, the reference already has the compile-time typeView
.If you want to know whether a type cast
(Foo)x
will succeed, you may usex == null || x instanceof Foo
as the type cast will also succeed whenx
isnull
(however, you should think twice whether you really want to acceptnull
s, even if the type cast will be successful)
PMD: how to deal with no need to check null before instanceof
If you can't use the fixed version of PMD, add a temporary variable
... principal = null;
if (SecurityContextHolder.getContext().getAuthentication() != null)
principal = SecurityContextHolder.getContext().getAuthentication()
.getPrincipal();
if (principal instanceof User) ...
Null instanceof Object
It probably just means that the IDEA code analyzier is not writtent to support this "use case". The analyzer is probably (intentionally) coded to detect the use of variables that have previously been assigned to null
, since this is a quite common mistake to make while coding, but the null instance of Object
case it not very common as very few programmers would write this while actually meaning something else.
There are many constructs like these that can not be correctly detected by static code analyzers like Sonar, Eclipse or IDEA. I would not worry much about it, just be aware that the IDE can not spot every mistake you make in your code.
Null Pointer Exception when calling variable from another class
I pasted your code and ran it locally. When prompted, I entered "100". Here's the entire output:
Input price of car
100
0.0
0.0
Exception in thread "main" java.lang.NullPointerException: Cannot read field "price" because "this.car" is null
at ComprehensivePolicy.calcPayment(main.java:102)
at main.main(main.java:17)
Why did that fail? Because Car car;
is declared in the abstract class, and code tries to use it (car.price
) without first assigning a value or creating a Car
object. So, car
is null, and calling anything on it (like "car.price") will throw NullPointerException.
Here's a very simple fix to get it working: right after creating a new "ThirdPartyPolicy", assign the car you created a few lines earlier:
Car c = new Car("model", 1998, 123);
...
ThirdPartyPolicy tp = new ThirdPartyPolicy("hello");
tp.car = c;
After doing that, you'll see another exception which looks identical to the first. It's due to the shared code in the abstract class, again with null "car". Here's a similar simple fix to get it working.
ComprehensivePolicy comp = new ComprehensivePolicy(2, 31);
comp.car = c;
After adding both of those lines, the program runs without error.
Here's a cleaner way of making things work.
- Modify the "ThirdPartyPolicy" constructor to require a
Car
parameter, and save the reference (this.car = car
):public ThirdPartyPolicy(Car car, String comments) {
this.comments = comments;
this.car = car;
} - Similar change for "ComprehensivePolicy":
public ComprehensivePolicy(Car car, int level, int driverage) {
this.car = car;
this.level = level;
this.driverage = driverage;
} - Pass the "car" reference to each of the constructors:
Car car = new Car("model", 1998, 123);
ThirdPartyPolicy tp = new ThirdPartyPolicy(car, "hello");
ComprehensivePolicy comp = new ComprehensivePolicy(car, 2, 31);
Error in using instanceOf operator in Java
There is a number of things that you can improve.
First, the instanceof keyword is lowercase.
Second, if you override equals(Object)
, you MUST also override hashCode()
, as mentioned in this answer. This answer also contains excellent examples of how to implement both equals
and hashCode
.
Third, your implementation allows name
to be null
, in which case this.getName()
is null
and your check
this.getName().equals(input.getName())
throws a NullPointerException
. I suggest you follow the more robust practice in the answer or this tutorial, or make sure that name
can never be null
, by checking it in the constructor and setName
.
Additional improvements and remarks
If there is a field ID
, I assume that it is there to identify the employee. In that case, it must be included in the equals
check.
If there is an 'ID`, why also check the name and the salary? Does changing the salary also mean that it becomes a different Employee? Same if I correct the name of the Employee?
The initialisation of ID
is not thread-safe, and can lead to different Employees having the same ID
. Consider doing:
import java.util.concurrent.atomic.AtomicInteger;
///
private static AtomicInteger lastID = new AtomicInteger();
And in the constructor just do
this.ID = lastID.getAndIncrement();
which makes the following line unnecessary:
Employee.lastID=Employee.lastID+1;
Another thing is that the method raise
also allows the salary to be set lower than its previous value. I would either check for that, or rename raise
to setSalary
.
Given all that, it would lead to something like:
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
public class Employee {
private static AtomicInteger lastID = new AtomicInteger();
private String name;
private final int ID;
private double salary;
public Employee(String name, double salary) {
this.name = name;
ID = lastID.getAndIncrement();
this.salary = salary;
}
public String getName() { return name; }
public int getID() { return ID; }
public double getSalary() { return salary; }
public void setName(String newName) { name = newName; }
public void setSalary(double newSalary) { salary = newSalary; }
@Override
public String toString() {
return "Name: " + getName() + "\nID: " + getID() + "\nSalary: " + getSalary();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Employee)) return false;
Employee employee = (Employee) o;
return ID == employee.ID;
}
@Override
public int hashCode() {
return Objects.hash(ID);
}
}
Related Topics
Is It Safe to Construct Swing/Awt Widgets Not on the Event Dispatch Thread
Jpa/Hibernate Native Queries Do Not Recognize Parameters
Import Xxx Cannot Be Resolved for Java Se Standard Classes
Manipulating and Comparing Floating Points in Java
Java, How to Add Library Files in Netbeans
How to Test Void Method with Junit Testing Tools
Instance Method Reference and Lambda Parameters
How to Pass List from Java to Oracle Procedure
How to Inject an Object into Jersey Request Context
Get Rid of "The Value for Annotation Attribute Must Be a Constant Expression" Message
Run .Exe File in Java from File Location
In What Order Are Static Blocks and Static Variables in a Class Executed
Paintcomponent() VS Paint() and JPAnel VS Canvas in a Paintbrush-Type Gui
Using a Jfilechooser with Swing Gui Classes and Listeners
Why to Use Stringbuffer in Java Instead of the String Concatenation Operator