Initializing Variables

R

Rhino

I've received some criticism recently with regards to the approach I use to
initializing variables so I'd like to throw this issue out to the whole
group so that I can learn more about the pros and cons of the approach I am
using....

Basically, I initialize pretty much every variable as I declare it, just to
be sure it has some kind of value right away. That initial value is
typically a zero for a number or a null for an object. Some recent
criticism questioned this practice so I thought I'd review some of the
material that helped get me in that habit in the first place.

The Java Tutorial, specifically
http://java.sun.com/docs/books/tutorial/java/nutsandbolts/datatypes.html,
says that, although non-local variables always get a default value anyway,
relying on that "is generally considered bad programming style". They also
point out that local variables are never assigned values in advance and
will cause compile-time errors if an unitialized variable is accessed.

Now, the Java Tutorial is aimed at Java beginners so this particular advice
may not be appropriate for people with more experience. I consider the
experts on this group a pretty advanced bunch so how do you feel about this
advice?
 
A

Arne Vajhøj

I've received some criticism recently with regards to the approach I use to
initializing variables so I'd like to throw this issue out to the whole
group so that I can learn more about the pros and cons of the approach I am
using....

Basically, I initialize pretty much every variable as I declare it, just to
be sure it has some kind of value right away. That initial value is
typically a zero for a number or a null for an object. Some recent
criticism questioned this practice so I thought I'd review some of the
material that helped get me in that habit in the first place.

The Java Tutorial, specifically
http://java.sun.com/docs/books/tutorial/java/nutsandbolts/datatypes.html,
says that, although non-local variables always get a default value anyway,
relying on that "is generally considered bad programming style". They also
point out that local variables are never assigned values in advance and
will cause compile-time errors if an unitialized variable is accessed.

Now, the Java Tutorial is aimed at Java beginners so this particular advice
may not be appropriate for people with more experience. I consider the
experts on this group a pretty advanced bunch so how do you feel about this
advice?

I strongly favor readability here. The extra overhead of something
getting initialized twice should be minimal or zero if the JIT
compiler optimizes it away.

Basically I would either initialize all the fields inline or
initialize no fields inline and assign values to all of them
in the constructor.

This ensures that:
- everything is initialized the same place
- everything has an explicit initialization

This is more readable in my opinion.

Arne
 
D

Daniel Pitts

I've received some criticism recently with regards to the approach I use to
initializing variables so I'd like to throw this issue out to the whole
group so that I can learn more about the pros and cons of the approach I am
using....

Basically, I initialize pretty much every variable as I declare it, just to
be sure it has some kind of value right away. That initial value is
typically a zero for a number or a null for an object. Some recent
criticism questioned this practice so I thought I'd review some of the
material that helped get me in that habit in the first place.

The Java Tutorial, specifically
http://java.sun.com/docs/books/tutorial/java/nutsandbolts/datatypes.html,
says that, although non-local variables always get a default value anyway,
relying on that "is generally considered bad programming style". They also
point out that local variables are never assigned values in advance and
will cause compile-time errors if an unitialized variable is accessed.

Now, the Java Tutorial is aimed at Java beginners so this particular advice
may not be appropriate for people with more experience. I consider the
experts on this group a pretty advanced bunch so how do you feel about this
advice?

I generally try to declare every field and local variable as "final" if
possible. In other words, I want my value to be initialized exactly
once. This doesn't always work with dependency injection frameworks,
but I use that as the guideline.

If a variable *can* be set more than once, you have a few things to
worry about.

First is, can I provide a sensible default value. The null value is
language provided default for reference fields, but often times there is
a better default value. One pattern I like to use is the "null object
pattern" <http://en.wikipedia.org/wiki/Null_Object_pattern>. This
obviates the need for null checks in many places, especially if you have
a setter method which replaces null with your null-object.

The second thing to worry about is consistency. If a variable can have
multiple values throughout its lifetime, then it becomes more
complicated understanding which value you are getting. Sometimes the
knowledge of "which" isn't necessary for understanding, but other times
it is. If you have a complex external algorithm which queries your
object several times, it could cause problems if the underlying data is
switched out from under it.

The third thing is there are concurrency concerns with non-final
references. I won't go into details, but Java Concurrency in Practice
can help:
<http://virtualinfinity.net/wordpress/technical-book-recommendations/java-concurrency-in-practice/>

So in general, I think initializing with a value you never expect to get
used is an error. If possible, instead of initializing, you should try
to find a way to cause a compiler error. Using final and local variables
are good for this. If you expect it to be used before it is
re-initialized, find a sensible default value. If you can't do either,
then at the very least document that fact very well, and throw
informative runtime errors if the value isn't initialized properly.

Also, if you have a complicated code-path necessary for determining the
initial value, try moving that into a private method which returns the
value. That can make it simpler to understand.
 
A

Arved Sandstrom

Rhino said:
I've received some criticism recently with regards to the approach I use to
initializing variables so I'd like to throw this issue out to the whole
group so that I can learn more about the pros and cons of the approach I am
using....

Basically, I initialize pretty much every variable as I declare it, just to
be sure it has some kind of value right away. That initial value is
typically a zero for a number or a null for an object. Some recent
criticism questioned this practice so I thought I'd review some of the
material that helped get me in that habit in the first place.

The Java Tutorial, specifically
http://java.sun.com/docs/books/tutorial/java/nutsandbolts/datatypes.html,
says that, although non-local variables always get a default value anyway,
relying on that "is generally considered bad programming style". They also
point out that local variables are never assigned values in advance and
will cause compile-time errors if an unitialized variable is accessed.

Now, the Java Tutorial is aimed at Java beginners so this particular advice
may not be appropriate for people with more experience. I consider the
experts on this group a pretty advanced bunch so how do you feel about this
advice?
I am in agreement with Arne here. Generally speaking I want to
understand not only when member and local variables are initialized but
also every time they are updated; initialization to me is not
intrinsically noteworthy, it's just the first assignment of value, but
often not the last.

In order to more clearly understand where (and by what) variables are
updated, readability is important. Restricting access and scope (and
using final) is important. Using setters even when you can access the
variable directly is often preferable.

So, generally speaking, if you can easily keep track of variable
assignments, including initialization, which means readable and
maintainable assignments, you've answered your question. There are no
magic rules for this otherwise.

AHS
 
J

Jim Janney

Rhino said:
I've received some criticism recently with regards to the approach I use to
initializing variables so I'd like to throw this issue out to the whole
group so that I can learn more about the pros and cons of the approach I am
using....

Basically, I initialize pretty much every variable as I declare it, just to
be sure it has some kind of value right away. That initial value is
typically a zero for a number or a null for an object. Some recent
criticism questioned this practice so I thought I'd review some of the
material that helped get me in that habit in the first place.

The Java Tutorial, specifically
http://java.sun.com/docs/books/tutorial/java/nutsandbolts/datatypes.html,
says that, although non-local variables always get a default value anyway,
relying on that "is generally considered bad programming style". They also
point out that local variables are never assigned values in advance and
will cause compile-time errors if an unitialized variable is accessed.

Now, the Java Tutorial is aimed at Java beginners so this particular advice
may not be appropriate for people with more experience. I consider the
experts on this group a pretty advanced bunch so how do you feel about this
advice?

"Just to be sure it has some kind of value" is a very weak reason for
initializing a variable. If you don't have a meaningful value for a
variable, throwing in a meaningless one just makes the code harder to
read. At the same time, most declarations should be initialized. How
is this possible? It's simple: don't declare a variable until you're
ready to give it a value. For example, here is a method from the
Apache Commons string utils:

public static String deleteWhitespace(String str) {
if (str == null) {
return null;
}
int sz = str.length();
StringBuffer buffer = new StringBuffer(sz);
for (int i = 0; i < sz; i++) {
if (!Character.isWhitespace(str.charAt(i))) {
buffer.append(str.charAt(i));
}
}
return buffer.toString();
}


You could move sz, buffer, and i to the top of the method and
initialize them with make-believe values, but it wouldn't be an
improvement.

There *are* times when you have to give a variable a value just to
make the compiler happy. Normally this is a sign that you should
rewrite the code, but sometimes you can't (for example, when
implementing a simple FSM). When I have to write a bogus
initialization I usually flag it with a comment.
 
L

Lew

Arne said:
I strongly favor readability here. The extra overhead of something
getting initialized twice should be minimal or zero if the JIT
compiler optimizes it away.

Minimal, perhaps, but the system is not permitted to optimize away member
initialization.
 
L

Lew

Daniel said:
So in general, I think initializing with a value you never expect to get
used is an error. If possible, instead of initializing, you should try
to find a way to cause a compiler error. Using final and local variables
are good for this. If you expect it to be used before it is
re-initialized, find a sensible default value. If you can't do either,
then at the very least document that fact very well, and throw
informative runtime errors if the value isn't initialized properly.

Also, if you have a complicated code-path necessary for determining the
initial value, try moving that into a private method which returns the
value. That can make it simpler to understand.

The thing I find objectionable is the pattern

Foo foo = null;
foo = actualInitialValue();

instead of

Foo foo = actualInitialValue();

Initializing a member variable to 'null' is all right, albeit mildly
unnecessary, if there's a chance its value will remain 'null', but I also
expect every Java programmer collecting pay for the knowledge to understand
that member values are already initialized to 'null' absent that explicit
initialization.

I expect anyone at least "intermediate" in Java to know that explicitly
initializing a member variable to 'null' causes the variable to be assigned
that value twice. If they accept that small overhead, fine, but they should
know of it.

Using 'final' and local variables (or both at once, 'final' local variables)
is always good when possible because the compiler tells you if you got it wrong.

The JLS has sections on "definitely assigned" and "definitely unassigned" that
are worth study.
 
T

Tom Anderson

...

I follow the extreme opposite view. I initialize a local variable at the
point of declaration if doing so makes logical sense or I know that I
know something the compiler does not know. Generally, that involves the
compiler assuming a fall-through from a call to System.exit.

The reason for doing this is simple. I make mistakes. I have done most
of my work in environments in which pair programming is not feasible, so
I cannot depend on another programmer to catch my mistakes. To the
maximum extent possible, I want to co-opt Eclipse's continuous source
code checking as an aid to finding my mistakes as quickly as possible.

One mistake I might make is omitting a logically necessary assignment to
a local variable. Routinely initializing at the point of declaration
would eliminate the possibility that it might be detected by the compiler.

When I get a definite assignment error I take the time to look at my
logic. Just occasionally, simply adding an initializer to the
declaration would leave either an actual error or unnecessarily
convoluted code, and I do something else.

This is exactly what i do. By initialising locals at the point of
definition, you immediately throw away the compiler's ability to
sanity-check your assignments to them. Don't do that.

tom
 
A

Arne Vajhøj

This is exactly what i do. By initialising locals at the point of
definition, you immediately throw away the compiler's ability to
sanity-check your assignments to them. Don't do that.

That is a good argument.

But I would note that in many cases the optimal solution is to
wait declaring the variable until you have a value to give it.

Arne
 
A

Arne Vajhøj

Minimal, perhaps, but the system is not permitted to optimize away
member initialization.

What would prevent the JIT compiler from optimizing the setting of
an int to zero twice to only doing it once?

Arne
 
L

Lew

What would prevent the JIT compiler from optimizing the setting of
an int to zero twice to only doing it once?

The JLS, section 12.5, "Creation of New Class Instances":
"In some early implementations, the compiler incorrectly omitted the code to
initialize a field if the field initializer expression was a constant
expression whose value was equal to the default initialization value for its
type."
 
A

Arne Vajhøj

The JLS, section 12.5, "Creation of New Class Instances":
"In some early implementations, the compiler incorrectly omitted the
code to initialize a field if the field initializer expression was a
constant expression whose value was equal to the default initialization
value for its type."

But isn't that talking about javac and not JIT?

Arne
 
L

Lew

But isn't that talking about javac and not JIT?

Not as I read it, but maybe it is.

Regardless, JIT requires multiple executions (by default 10,000 IIRC) before
it decides to optimize something. By definition, initialization code is run once.

Regardless, as you pointed out and I reiterated, the performance impact is not
enough to trump issues of readability or self-documentation. Nor is it
required to initialize member variables to their default values.

I admit it's possible that I read this wrong, but I think not.
 
J

Jim Janney

Tom Anderson said:
This is exactly what i do. By initialising locals at the point of
definition, you immediately throw away the compiler's ability to
sanity-check your assignments to them. Don't do that.

You've lost me here. We all make mistakes, but I don't see how this
is supposed to help. Perhaps someone could post a short example?
 
A

Alan Malloy

Jim said:
You've lost me here. We all make mistakes, but I don't see how this
is supposed to help. Perhaps someone could post a short example?

void printList(MyLinkedList list) {
MyNode n = null;
// Some other initialization code

// forgot to uncomment the next line
// n = list.first();

while (n != null) {
print(n);
n = n.next();
}
}

Without the initial null assignment, the compiler will let you know
you've made a mistake. Putting it there destroys the read-before-use
checking and causes the method to do nothing at runtime, with no error
detection at all.
 
T

Tom Anderson

That is a good argument.

But I would note that in many cases the optimal solution is to
wait declaring the variable until you have a value to give it.

Absolutely. Goes without saying!

tom
 
A

Arved Sandstrom

[ SNIP ]
You've lost me here. We all make mistakes, but I don't see how this
is supposed to help. Perhaps someone could post a short example?
Tom's observation follows from Patricia's comment about _routinely_
initializing at the point of declaration, Jim. And Patricia's comment
refers to premature declarations (*). Without those qualifications then
his observation would be quite absurd, I agree. :)

AHS

* I don't use the word "premature" disparagingly. For reasons of clarity
or scoping a local variable may be declared before a suitable value can
be assigned.
 
P

Pitch

although non-local variables always get a default value anyway,
relying on that "is generally considered bad programming style".


I explicitely declare a variable null only to show other programmers
that I will explicitely check if it's null at some point. That means
it's not an ordinary type field but a flag.

So it's a matter of our in-house coding standard.
 
G

Gunter Herrmann

Tom said:
Absolutely. Goes without saying!

There are exceptions to this rule (pun intended)

Foo foo = null;

try {
foo = new Foo();
foo.doProcessing();
}
catch (FooException ex) {
doSomething(ex);
}
finally {
foo.cleanup();
}

In this case you have to initialize the variable foo.

brgds

Gunter in Orlando, Fla.
 
J

Jim Janney

Alan Malloy said:
void printList(MyLinkedList list) {
MyNode n = null;
// Some other initialization code

// forgot to uncomment the next line
// n = list.first();

while (n != null) {
print(n);
n = n.next();
}
}

Without the initial null assignment, the compiler will let you know
you've made a mistake. Putting it there destroys the read-before-use
checking and causes the method to do nothing at runtime, with no error
detection at all.

OIC, thanks.
 

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,770
Messages
2,569,583
Members
45,074
Latest member
StanleyFra

Latest Threads

Top