NullPointerException

E

elingtse

Hi all,

I am a newbie of Java and am working on my homework. I got an error
message "NullPointerException" after compilation. I know this means
values cannot be passed to array but it seems not my case because it
can generate a correct output on screen. The program terminate
abnormally after this error message. Could anyone help to point out
what I did wrong, thanks a lot.

et

Compilation Output :
------------------------------
Accounts of Amy
1234 : $1000.0
1122 : $5000.0
Exception in thread "main" java.lang.NullPointerException
at Person.displayAccount(Person.java:29)
at TestPerson.main(TestPerson.java:23)

Person Class
--------------------
public class Person {

//attributes
private String name;
private Account[] account = new Account[10];

//constructor
public Person(String name, Account[] account){
this.name = name;
this.account = account;
}

//create getter for name
public String getName(){
return name;
}

//create setter for name
public void setName(String setName){
name = setName;
}

//create displayAccount method
public void displayAccount(){
System.out.println("Accounts of " + name);
for(int i=0; i<account.length; i++){
System.out.println(account.getNumber() +" : $"+
account.getBalance());
}
}

//create lowBalanceAccounts method
public String lowBalanceAccounts(double lowBalance){
String msg = "No account's balance is lower than Low balance";
for(int i=0; i<account.length; i++){
if(account.getBalance() < lowBalance)
return account.getNumber();
}
return msg;
}

//create highestBalanceAccount Method
public String highestBalanceAccount(){
double hBal = 0;
String acNo = null;
for(int i=0; i<account.length; i++){
if(account.getBalance() > hBal){
hBal = account.getBalance();
acNo = account.getNumber();
}
}
return acNo;
}

}

TestPerson Class
--------------------------

//The class of TestPerson creates an environment
//for testing Person object

public class TestPerson {

public static void main(String Arg[]) {

//Attribute
int accountCount = 0;
Account[] account = new Account[10];

//create account and person objects for Amy
Account account1 = new Account("1234", 1000);
Account account2 = new Account("1122", 5000);
account[0] = account1;
account[1] = account2;
Person amy = new Person("Amy", account);

//System.exit(-1);


//call displayAccounts method
amy.displayAccount();

//call lowBalance accounts
System.out.println("Low balance account(s) :
"+amy.lowBalanceAccounts(2000));

//call highestBalanceAccount
System.out.println("The highest account is :
"+amy.highestBalanceAccount());

}
}
 
A

Andrew Thompson

Hi all,

I am a newbie of Java and am working on my homework.

The best group for people learning Java is
..I got an error
message "NullPointerException" after compilation.

That would be 'at Runtime'.
..I know this means
values cannot be passed to array but it seems not my case because it
can generate a correct output on screen. The program terminate
abnormally after this error message. Could anyone help to point out
what I did wrong, thanks a lot.

et

Compilation Output :

This is 'Runtime Output:'

Yes, you created (instantiated) two accounts in the
TestPerson main..
Exception in thread "main" java.lang.NullPointerException
at Person.displayAccount(Person.java:29)

...but your array has a size of 10 and 8 of those
array references point to nothing, or 'null', so
if you iterate them all, you should expect 8 NPE's
(unless you check each for null).
at TestPerson.main(TestPerson.java:23)

Person Class
....

And as an aside, this is not compilable code
(it is missing 'Account' class, for example, and
I had to correct problems caused by line wrap before
I discovered that), and you will generally get more
help if you post the miminal example that displays
the problem. More tips here..
<http://www.physci.org/codes/sscce.jsp>

HTH
 
E

elingtse

Hi Andrew,

Thanks for your help. I got the problem now though I still don't know
how to fix it. I guess I may use if(account != null) to check it
first.

Noted the sscce and will try to display example better next time. Sorry
for missing Account class, I thought the NPE is not from Account class
so no need to display. (I should stand at the position of reader).

et
 
D

David Wahler

Hi all,

I am a newbie of Java and am working on my homework. I got an error
message "NullPointerException" after compilation. I know this means
values cannot be passed to array but it seems not my case because it
can generate a correct output on screen. The program terminate
abnormally after this error message. Could anyone help to point out
what I did wrong, thanks a lot. [snip]
Exception in thread "main" java.lang.NullPointerException
at Person.displayAccount(Person.java:29)
at TestPerson.main(TestPerson.java:23) [snip]
public class TestPerson {

public static void main(String Arg[]) {

//Attribute
int accountCount = 0;
Account[] account = new Account[10];

OK -- account is an array of 10 references to Account, all of which are
null.
//create account and person objects for Amy
Account account1 = new Account("1234", 1000);
Account account2 = new Account("1122", 5000);
account[0] = account1;
account[1] = account2;
Person amy = new Person("Amy", account);
[snip]

account is now equal to
{account1,account2,null,null,null,null,null,null,null,null}. As soon as
you try to call a method of one of those null references, you'll get an
exception. Try using "Account[] account = new Account[2]" instead.

-- David
 
R

Roedy Green

System.out.println(account.getNumber() +" : $"+
account.getBalance());


You did not tell us which line 29 was. I am guessing this one.

You only filled in two accounts and attempted to print ten..

You either need to keep track of how many use filled, or use an
ArrayList instead of an array which does that for you.
 
G

Googmeister

Also, as a style issue, note that it is pointness to
initialize the instance variable account

private Account[] account = new Account[10];

since you reassign its value in the only constructor.
 
C

Chris Smith

For the reasons David Wahler showed, it might be better in general to
avoid the new Type[int] syntax, where Type is non-primitive, to prevent
NullPointerExceptions, as per:

Okay, this is silly. You seem to be here on a mission to post links to
that that ill-conceived article as many times as you can find excuses
for it.

So tell me: how do you create an array, then, if you don't know the
length at compile-time?

--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
R

Roedy Green


The cure sounds worse than the disease.

Do not use the keyword 'null'

Make all fields final to force compile error for non-initialisation.

Do not use the new Type[int] syntax for creating arrays of objects
use Object[] x = { thing, thing2 };

Do not use reflection (thus cheating to create an array full of null
pointers)

I don't know what you are supposed to use in place of null, say "" for
strings? You may just be sweeping problems under the rug.
 
A

Andrew McDonagh

Roedy said:


The cure sounds worse than the disease.

Do not use the keyword 'null'

Make all fields final to force compile error for non-initialisation.

Do not use the new Type[int] syntax for creating arrays of objects
use Object[] x = { thing, thing2 };

Do not use reflection (thus cheating to create an array full of null
pointers)

I don't know what you are supposed to use in place of null, say "" for
strings? You may just be sweeping problems under the rug.

I kind of agree and disagree...

There's nothing wrong with these techniques themselves, though the site
touts them as being the whole story - which they are not.

Essentially what the page is trying to show, is that its certainly
possible to create exception safe code that substantially reduces the
problems encountered by null pointer exceptions.

This is not a new technique.

There's plenty of ways of achieving this too, NullObject Pattern, return
zero sized collections or arrays instead of nulls, etc.

The reflection one is too weird for me to figure out what the supposed
benefit is though....
 
R

ricky.clarkson

So tell me: how do you create an array, then, if you don't know the
length at compile-time?

final List<String> strings=new ArrayList<String>();

int total=(int)(Math.random()*100+100);

for (int i=0;i<total;i++)
strings.add("number "+i);

final String[] array=(String[])strings.toArray(new String[0]);

Ok, the concession there is that I have used new String[int value], but
the value is 0, so there are no null pointers there.
I don't know what you are supposed to use in place of null, say "" for
strings? You may just be sweeping problems under the rug.

Roedy, the point is that you don't need these default values. If you
find you need a default value, you might be creating an object before
you're ready for it.

So it doesn't really matter whether it's null, "" or "unknown", you're
better off with real data, if possible. Direct from TFA:

"You might also consider replacing null with "" in the first example,
but default values bring about bugs caused by default values being left
in place. A NullPointerException is actually better, as it allows the
runtime to tell you about the bug, rather than just continue with a
default value."

Andrew McDonagh,

Specifically, what I am against is the NullObject pattern. I want real
data. Except in the case of mocking for automated tests, I'd rather
have no object than an object populated with dummy data.

Wrt the reflection bit, I added a phrase just now to the article, to
clarify:

"This is not a ban on reflection, it is just to warn that circumventing
the rule on new Object[10] by using Arrays.newInstance has the same
problem."
 
R

Roedy Green

final List<String> strings=new ArrayList<String>();

int total=(int)(Math.random()*100+100);

for (int i=0;i<total;i++)
strings.add("number "+i);

final String[] array=(String[])strings.toArray(new String[0]);


That code is more complicated, and much slower than:

int size = ...;
final String[] strings = new String[size];
for (int i=0; i<size; i++)
{
strings = "number" + i;
}
 
A

Andrew McDonagh

Roedy said:
final List<String> strings=new ArrayList<String>();

int total=(int)(Math.random()*100+100);

for (int i=0;i<total;i++)
strings.add("number "+i);

final String[] array=(String[])strings.toArray(new String[0]);



That code is more complicated, and much slower than:

int size = ...;
final String[] strings = new String[size];
for (int i=0; i<size; i++)
{
strings = "number" + i;
}


We don't care about speed until a profiler tells us there is a problem
with the speed - premature optimisation (a google-able term) sucks for
many good reasons.

The code is no more complicated in my books..ymmv
 
A

Andrew McDonagh

(e-mail address removed) wrote:

snip
Roedy, the point is that you don't need these default values. If you
find you need a default value, you might be creating an object before
you're ready for it.

So it doesn't really matter whether it's null, "" or "unknown", you're
better off with real data, if possible. Direct from TFA:
TFA?


"You might also consider replacing null with "" in the first example,
but default values bring about bugs caused by default values being left
in place. A NullPointerException is actually better, as it allows the
runtime to tell you about the bug, rather than just continue with a
default value."

Andrew McDonagh,

Specifically, what I am against is the NullObject pattern. I want real
data. Except in the case of mocking for automated tests, I'd rather
have no object than an object populated with dummy data.

Thats not my understanding of NullObject - its a simple implementation
that returns false/true, 0, "", empty Collections, etc. Its specifically
so that we don't have to test for nulls everywhere, but in a safe
manner. We wouldn't use it to return data that c/would cause us problems.

Sometimes (rarely) its useful to throw specific exceptions e.g.
(NoInformListenersToInformOfStateChangeException). As it puts context
information into what would have originally been a null pointer exception.


Andrew
 
R

ricky.clarkson

TFA?

Sorry, slashdot slang - the f**king article. I don't even use slashdot
(other than reading the headlines sometimes), but that one stuck in my
head.
Thats not my understanding of NullObject - its a simple implementation
that returns false/true, 0, "", empty Collections, etc. Its specifically
so that we don't have to test for nulls everywhere, but in a safe
manner. We wouldn't use it to return data that c/would cause us problems.

Except that last sentence, I agree. However, I think NullObjects can
cause problems, because they are providing a way of not testing for
null. It is better to not have a value than to have either a
NullObject or null.

For example:

interface BananaGiver
{
/**
@return a banana or null if there is no banana
*/
Banana getBanana();
}

I'd rather have:

interface BananaGiver
{
boolean hasBanana();

/**
@throws IllegalStateException if there is no banana.
*/
Banana getBanana();
}

Of course, there is the difficulty that a banana might appear between
calling hasBanana and calling getBanana, but that can be included in a
documentation contract.

I'd even prefer the one method, getBanana(), that throws an
IllegalStateException, over something that might return null.
Sometimes (rarely) its useful to throw specific exceptions e.g.
(NoInformListenersToInformOfStateChangeException). As it puts context
information into what would have originally been a null pointer exception.

Agreed, but unless it's a checked exception that you throw, there's
rarely a case where that would make a real difference. The NPE at
least tells you where to look.

In the case of NoInformListenersToInformOfStateChangeException, that
looks like it should be on the bad end of an if statement:

if (informListeners.isEmpty())
throw new NoInformListenersToInformOfStateChangeException();

for (final InformListener....

I don't see a NPE to handle there, unless informListeners is null,
which is undesirable.
 
C

Chris Smith

final List<String> strings=new ArrayList<String>();

int total=(int)(Math.random()*100+100);

for (int i=0;i<total;i++)
strings.add("number "+i);

final String[] array=(String[])strings.toArray(new String[0]);

Okay, so you can do that, but it's definitely more complicated.

More importantly, the only reason that the Collections API can implement
toArray is that it doesn't follow your rules. You are setting things up
so that a programmer needs to hope that there's some API to do stuff for
him, because he's not allowed to write code to do so himself. That
seems short-sighted.
Roedy, the point is that you don't need these default values. If you
find you need a default value, you might be creating an object before
you're ready for it.

I don't think you have a single shred of evidence that you don't need
default values.

For one thing, it's exceedingly difficult to create a programming
language in which it's not possible to observe a null value. Java is
certainly not that language, and it's trivial to write code that
observes the default (null) values of reference fields, even if you
never assign values of null to the fields, declare them final, and
follow all of your recommendations.

Considerably more relevant is the simple fact that problems domains
often contain objects that either are or aren't there. You don't have a
good answer to that problem. Sometimes the null object pattern can
suffice for potentially non-existent objects that need to be modelled in
software, but you seem opposed to that, as well. The only possibility
that you've left open is to keep a list or array and just document a
constraint that it must have either zero or one elements at all times;
which is ludicrously convoluted as a solution to a simple task.

I'd rather have:

interface BananaGiver
{
boolean hasBanana();

/**
@throws IllegalStateException if there is no banana.
*/
Banana getBanana();
}

And this makes the point. Please provide an implementation of that
interface that either can or cannot have a banana, depending on the
object's state.

You seem to have serious problems with null or NullPointerException. I
don't know where they come from... but I have to agree with John, that
it would be better to educate people about the null value and the
problem with dereferencing it. Adding complexity to the use of the
language is no solution.

--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
R

ricky.clarkson

Chris Smith,
Okay, so you can do that, but it's definitely more complicated.

The only line that's more complicated is the toArray line, which is
just a sad artefact of the limitations of generics. If generics
existed at runtime, we would have:

String[] array=strings.toArray();

In fact, a slight change to Collection could yield this:

String[] array=strings.toArray(String.class);

without any real language change.
More importantly, the only reason that the Collections API can implement
toArray is that it doesn't follow your rules.

Yes, this is definitely true. But, if an API exists to do something,
why not use it? Plus, if you know HOW to avoid NullPointerExceptions,
absolutely, then you can CHOOSE when to break the rules. E.g., you may
allocate a 100 element array, but you trust yourself enough to fill
each item before you give it away to any other code that is not
expecting null.

Null might be required in certain circumstances, but it shouldn't be
everywhere in your code if you don't want NullPointerExceptions. It
should be isolated.
For one thing, it's exceedingly difficult to create a programming
language in which it's not possible to observe a null value.

Probably. I haven't written a programming language for ages. Does the
reference system in C++ count? I never used it extensively, the
compiler error messages foxed me, so I stuck with pointers.
Java is
certainly not that language, and it's trivial to write code that
observes the default (null) values of reference fields, even if you
never assign values of null to the fields, declare them final, and
follow all of your recommendations.

Yes, I think this exhibits the issue:

final class X
{
private final Object y=x;
private final Object x=new Object();
}

I'm sure there are other ways too. I do think that making fields
readable before they have been assigned (especially final fields) is a
mistake in the language. Note that 'they' don't assign default values
to local variables.
Considerably more relevant is the simple fact that problems domains
often contain objects that either are or aren't there.

Very true, but even then there is no reason for the *interface* to
expose null.

interface Student
{
String getName();
String getAddress();
}

If we don't know where the Student lives, we might return null, which
could cause problems for calling code.

interface Student
{
String getName(); //we always know the name!
boolean hasAddress();
String getAddress() throws IllegalStateException;
}

So yes, the simplest implementation would be a possibly-null reference
to a String, but that 'null' is isolated. Having a zero-length
collection is pretty pointless there - I don't really know where that
came from.
Adding complexity to the use of the
language is no solution.

Passing null to methods that don't expect it is also no solution.

My point of view is of someone who wants to reduce bugs. Like it or
not, testing is not comprehensive. This doesn't mean the program
should be able to recover from all bugs, but it does mean that the
program should be written in such a way that bugs are less likely,
where it is practical.

Default values, except where they are present in a problem domain, seem
only to serve to mask bugs.

I think these constraints are practicable, for more problems than you
might expect.
You seem to have serious problems with null or NullPointerException.

I have serious problems with bugs. I don't like them. A
NullPointerException seems like a beginner's bug, but people who seem
to know what they're doing still cause them (myself included - I
haven't applied these rules very far yet). So I just think that
instead of becoming very fast at fixing the bug we should become better
at preventing the bug. Ask a doctor whether this makes sense.
 
C

Chris Smith

Paring this down to what's important...

Null might be required in certain circumstances, but it shouldn't be
everywhere in your code if you don't want NullPointerExceptions. It
should be isolated.

NullPointerException is a runtime error that indicates a failure of an
assumption made about a variable... that it points to an object. This
is exactly analogous to other bad values of variables. I often declare
int variables in Java that I expect to remain non-negative, or less than
one hundred, or whatever. Context constrains the possible values of a
data type, no matter what you do. With integer types, I might code
assertions to check these constraints. With null values, the compiler
provides NullPointerException to do it. The fact that my code can throw
a NullPointerException is a GOOD THING. It helps to diagnose problems.

And therein lies the problems with your article. Null values are not
bugs. NullPointerException is not even a bug; rather, it's a
deterministic way to find and report a bug. By avoiding the symptom,
the problem can be buried and harder to find... or at best, still there.
There's no reason to believe that your rules lead to better code. They
just lead to fewer references with a value of null, and more time wasted
writing code to work around the rules.
A NullPointerException seems like a beginner's bug

No, it doesn't. It's no more a beginner's bug than any other. It
indicates a flawed assumption about an API. The immediate solution is
to identify that assumption and fix it. The long-term solution is to
understand the API and problem space better.

The problem appears to be that you assume a NullPointerException is an
error that comes from making a mistake with the null value. In reality,
NullPointerException comes from things like:

* I thought we could safely assume this request attribute was set in the
previous HTTP request, but someone found a different path to this code.

* I thought this path name was guaranteed to be a directory, but it's a
file instead and therefore doesn't have children.

* I thought the username had already been authenticated and always
exists on the LDAP server, but someone passed in a synthetic username
instead.

In all cases, a NullPointerException doesn't come from a poor
understanding or treatment of the null value; it comes from a failed
assumption about the software. It's not a mechanical thing to fix, but
rather involves evaluating what's been newly learned about the software.
Your rules cannot possibly help with that.

My fear is that you're peddling a magic pill, claiming that we don't
need to really understand the language because we need only follow your
simple rules and be safe. But that's not true. Following your rules
only turns one bug into another, while making certain tasks impossible
and others more complex and therefore more likely to contain bugs.

--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
R

Roedy Green

No, it doesn't. It's no more a beginner's bug than any other. It
indicates a flawed assumption about an API. The immediate solution is
to identify that assumption and fix it. The long-term solution is to
understand the API and problem space better.

It is a beginner's bug in that beginners generate a lot of them being
careless about initialising objects.

Using local variables wherever possible turns on initialisation
checking you don't get with static or instance variables.

I think the reason Gosling decided to make all instance and static
variables autoinitialising to null is that if he did not, there would
be no way at compile time to detect the error.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,818
Messages
2,569,736
Members
45,708
Latest member
RenaldoFor

Latest Threads

Top