We are about to switch to a new forum software. Until then we have removed the registration on this forum.
One of the most common errors in Java (hence, in Processing) is this NullPointerException (short-named NPE). Fortunately, it is also one of the easiest to fix, once the most common cases are known.
First, what is this name? It is one of the most misnamed class of Java, because this language has no pointers! This has probably historical roots, when people wrote the Java compiler in C or C++, where the word 'pointer' comes from. Java has no pointers but references, which fill the same role, in a safer way (no risk of memory corruption!).
An Exception is a language mechanism allowing to handle exceptional cases, usually errors. Your program, or some class, throws an exception when an unrecoverable error happens (programming mistake, file isn't there, program can't connect to network, etc.) and should be handled at a higher level (by the programmer).
Some of these errors come from a programming error, so you just fix the error to get rid of it (we will see that for NPE here), others, like not being able to open a file, must be handled by a try / catch
construct, but that's outside of the scope of this article.
And what is Null, or, rather, null
? It is a special Java value, indicating that an object reference hasn't been initialized yet (or have been reset). It is also often used as return value from functions supposed to return an object, to indicate an error has happened and the object isn't available. Processing does that a lot, because it wants to avoid exposing exceptions to users, as they are quite complex to handle.
So, when you declare a global object, it is null:
PImage sprite;
int[] times;
PVector[] positions;
ArrayList balls;
Player player;
Yes, an array in Java is an object.
If you try to use these objects in this state, you will get NPEs:
image(sprite, 10, 200);
int n = times[v];
float x = positions[i].x;
Ball b = balls.get(i);
player.update();
All these lines will raise a NullPointerException. You need to initialize them before using them.
Sometime, you can initialize the object at the declaration site:
int[] times = new int[BALL_NB];
PVector[] positions = new PVector[10];
ArrayList balls = new ArrayList();
Player player = new Player(5, 5, true);
and sometime you need to initialize them in the code itself, usually in setup()
as lot of objects are expensive to create (particularly when loading data from the disk) and this operation should be done once. Idem when you need values available only when setup()
is run.
void setup()
{
size(500, 500); // Remember! This call should be the first one of setup().
sprite = loadImage("scene.jpg"); // Costly call
positions = new PVector[width / 10]; // width is known only after the call to size()
Player player = new Player(width / 2, height / 2, true); // Intentional mistake here!
}
Of course, don't initialize twice: no need to do an init at declaration level if you need to initialize in setup(), the first value will just be lost.
There is an error in the last line of setup()
above. Can you see it? It is a quite common error meet by beginners...
This line actually declares a ''''new'''' player
local variable, that just hides the global variable of same name, and that disappears at the end of setup()
(its scope). So, when setup()
is finished, the global player
remains uninitialized, and you will get the dreaded NPE when trying to use it.
The solution is simple: just remove the type, which transforms the re-declaration into a simple assignment:
player = new Player(width / 2, height / 2, true);
You can also have a NPE when trying to use sprite
. In this case, that's loadImage()
that returned null
because it couldn't load the image.
The most usual causes is forgetting to put the image, putting it at the wrong place (not in the data
folder), mistyping the name (including case errors in non-Windows systems), having a corrupted file, etc.
The arrays are an interesting special case.
The times
array is ready to be used, because it is made of a primitive type: they are initialized with a default value, which is 0
(zero) for int
and float
(and char
, etc.), false
for booleans, null
for objects (including String
)...
The positions
array isn't ready, and you will get a NPE when trying to use it like positions[i].x = 10;
That's because after creating the array of objects, you need to initialize each object in it: this is actually just an array of references to objects, and these objects don't exist yet, so it is only an array of null values.
So you need to iterate on the array and assign a new object on each slot:
for (int i = 0; i < positions.length; i++)
{
positions[i] = new PVector(); // Can have a default value or something significant
}
That's the most commonly meet errors raising this exception, understanding the mechanism behind should help you finding the others...
You can ask help in the forum.
Of course, you have to provide the code where the NPE is found. It can be useful, too, to provide the stack trace displayed in the console by the PDE. For example:
Exception in thread "Animation Thread" java.lang.NullPointerException
at sketch_apr20a.displayStar(sketch_apr20a.java:36)
at sketch_apr20a.draw(sketch_apr20a.java:65)
at processing.core.PApplet.handleDraw(Unknown Source)
at processing.core.PApplet.run(Unknown Source)
at java.lang.Thread.run(Thread.java:662)
tells lot of information. We can see in this case it happened in a sketch not saved (sketch_apr20a
is a name generated by Processing for these cases), in the displayStar()
function called from the draw()
function.
The given line number (36 here) doesn't tell much, as it is the line in the sketch_apr20a.java
generated file, ie. a Java file created by Processing from the .pde file(s), with more lines, so it isn't usable in the .pde file.
But when you have such exception, the PDE highlights the line that failed. Examine it, use println()
before this line to see the relevant values, and if you are still stuck, indicate this line in your report in the forum.
Now, there is a special case where a line isn't highlighted: when the NPE happens in the global declarations of the sketch. In this case, the stack trace can look like:
Exception in thread "main" java.lang.RuntimeException: java.lang.NullPointerException
at processing.core.PApplet.runSketch(Unknown Source)
at processing.core.PApplet.main(Unknown Source)
Caused by: java.lang.NullPointerException
at sketch_apr20a.(sketch_apr20a.java:62)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at java.lang.Class.newInstance0(Class.java:355)
at java.lang.Class.newInstance(Class.java:308)
... 2 more
Notice the <init>
location, showing no function has been called yet. This shows that a global variable have been used without being initialized first. A simple way to reproduce this is, for example:
PVector pos; // Not initialized, it is null
int val; // Here, not initialized implies it is zero
float posX = pos.x; // You get an NPE here, because pos is null
In this case, you can defer the initialization of posX
to setup()
, if that's where the pos
object is initialized.