Test to see of a variable has been used/initialised

E

Eric Sosman

Anon said:
Hi,

How do I find out if a variable has been used or initialised yet?

If it's a local variable in a method, the compiler will
complain if it thinks the variable might be used before
being initialized. The compiler will sometimes issue bogus
complaints, but if it issues no complaint you can be sure
the variable is initialized before use.

If it's an argument of a method or constructor, it is
initialized by the method's caller or by the `new' expression.

If it's a class variable it is always initialized, either
when an object is constructed (for instance variables) or when
the class is loaded (for static variables). However, you and
Java may disagree about what "initialization" really means:
the variable will acquire a legitimate value of some kind due
to Java's own actions, but that's not a guarantee that your own
application-specific "initialization" has been performed:

/** A mutable integer. */
class Goof {
int number; /* Java initializes this to zero */

/** Constructs a new Goof with the given value. */
Goof(int number) {
number = number; // intended: `this.number = ...'
/* `this.number' is "uninitialized" in the sense
* your application intended, even though it is
* "initialized" from Java's point of view. */
}
}

The best way to deal with errors of this sort is, of course,
not to commit them ;-) If perfection is not an option, you may
sometimes be able to "Java-initialize" a variable with a value
that makes no sense to your application, so your application can
later recognized that value as meaning "somebody goofed." The
value `null' can often be used this way for reference variables;
the method is more difficult to apply to non-reference types.
 
M

Michiel Konstapel

How do I find out if a variable has been used or initialised yet?

What do you mean? Instance and class variables are automatically
initialised to zero, false or null. For local variables, the compiler
enforces that they have been assigned before use.
Michiel
 
J

John C. Bollinger

Anon said:
How do I find out if a variable has been used or initialised yet?

To check for user initialization, you can compare the value against the
default value or instance initialization value. Of course that fails if
the user initializes the variable to its default value, or later sets it
to that value. If you *must* reliably determine this then you can make
sure that initialization can only be performed via an instance method,
and then let the object track whether or not that method has been invoked.

As for usage, you'll have to define more precisely what you mean to get
any answer. It will in any case involve protecting access to the
variable by a method, as there is *no* way in standard Java to determine
whether or if a field has been read directly.

NOTE WELL, however: if your design depends on being able to determine
this sort of thing, then probably it is severely broken. In general,
instead of writing your classes in such a way as to have a need to check
such things, you should write them so that they only allow permitted
operations. And, no, that is in general not a circular requirement.


John Bollinger
(e-mail address removed)
 
A

Anon

Hi all,

Thanks for the tips.

The program I'm developing needs to decide whether or not to do something
(buy/sell an equity) based on order types (limit/market/stop). And I was
initially planning to test for the presence of the different order types
(e.g. stop orders are optional and may not always be present) by testing for
initialisation of the different parameters. However, judging by your
responses I believe it may be wiser to use boolean variables to flag weather
or not the variables have already been set or not.

Thanks again!

Anon.
 
T

Tony Morris

The compiler will sometimes issue bogus complaints,

Care to back this up with a bug report ?
Sounds like baloney to me.

--
Tony Morris
(BInfTech, Cert 3 I.T.)
Software Engineer
(2003 VTR1000F)
Sun Certified Programmer for the Java 2 Platform (1.4)
Sun Certified Developer for the Java 2 Platform
 
V

Virgil Green

steve said:
So you are saying a null variable is initialised ?

Absolutely. An unitialized variable would contatin whatever garbage was
previously hanging around in that memory location. Null, in this case, is
definitely the result of initialization.

- Virgil
 
T

Tony Morris

So you are saying a null variable is initialised ?

No.
The concept of a "null variable" is undefined in this context (the Java
Programming Language).

The suggestions that the compiler will complain if a variable may not have
been explicitly initialized apply to local variables only.
For example:

void m()
{
// local variable
int x;

if(something == 42)
{
x = 7;
}

// Compile error - x may not have been initialised.
System.out.println(x);
}

A member variable is always implicitly initialized (AND (not OR - this can
be demonstrated if need be) optionally explicitly initialized).
The default value that a member variable is explicitly initialized to is
dependant on the type of the varaible - I suggest reading the Java Language
Specification or an appropriate tutorial to learn these values.

class C
{
// member variable
int x;

void m()
{
// fine - x has been implicitly initialized to 0
System.out.println(x);
}
}


--
Tony Morris
(BInfTech, Cert 3 I.T.)
Software Engineer
(2003 VTR1000F)
Sun Certified Programmer for the Java 2 Platform (1.4)
Sun Certified Developer for the Java 2 Platform
 
T

Tony Morris

Absolutely. An unitialized variable would contatin whatever garbage was
previously hanging around in that memory location. Null, in this case, is
definitely the result of initialization.


No, it wouldn't contain anything - it would simpyly be uninitialized and
prevented from use.

Java != C

--
Tony Morris
(BInfTech, Cert 3 I.T.)
Software Engineer
(2003 VTR1000F)
Sun Certified Programmer for the Java 2 Platform (1.4)
Sun Certified Developer for the Java 2 Platform
 
R

Roedy Green

However, judging by your
responses I believe it may be wiser to use boolean variables to flag weather
or not the variables have already been set or not.

If at all possible never allow objects to exist that are in an
dangerous half-baked state. Make the constructor them at least to a
non-dangerous minimalist state.

No one should have to be testing fields before touching an object.

Another way to do it, which unfortunately is exceedingly clumsy in
java is to have a set of classes like nested dolls.

An object starts out small, and as you discover more, it adds layers
with new fields to hold the additional information.

You know how complete it is by its type. You CAN'T write code that
uses the object improperly!

The catch is there is no easy way to covert a Dog to a Dalmatian and
then add the Dalmatian-specific fields. You need a copy constructor
that takes a Dog, and then fishes the fields out of Dog one by one.
PHHT! Very error prone, hard to maintain, and can't clone private
fields.

I wish there were some shortcut to do this. In assembler, it could be
implemented with single move instruction, to copy over the common
part.
 
R

Roedy Green

So you are saying a null variable is initialised ?

Yes, null is a value. Uninitialised variables is C have a random
value in them left around from the last guy who used the RAM.

That never happens in Java. Either Java nulls/zeroes for you, or
forces you to set locals to something, possibly null/0.
 
L

Larry Barowski

Tony Morris said:
Care to back this up with a bug report ?
Sounds like baloney to me.

It's not a bug. The problem of determining if a variable is initialized is
not computable (for those not familiar with computational theory, this
basically means "impossible to solve in the general case using an
algorithm").

Here is a simple example:

int j;
int i = 5;
if(i == 5)
j = 0;
j++;

Here is an example you could not expect any compiler to catch
(assume you have a method to compute the nth digit of pi):

int j;
if(digitOfPI(98000009) == 3)
j = 0;
j++;

-Larry Barowski
 
C

Chris Uppal

Eric said:
If it's a local variable in a method, the compiler will
complain if it thinks the variable might be used before
being initialized. The compiler will sometimes issue bogus
complaints

I think the wording you've choosen is a bit misleading.

The complaints are "bogus" in the sense that a different analysis with
different rules might have recognised the case.

However they are not "bogus" in the sense of being wrong. There are definite
rules for deciding whether a variable has been intialised before use, those
rules are part of the definition of the Java language, and the compiler follows
them -- it is not allowed any choice. There may be bugs, of course, but I,
personally, don't know of any.

-- chris
 
T

Tony Morris

Larry Barowski said:
It's not a bug. The problem of determining if a variable is initialized is
not computable (for those not familiar with computational theory, this
basically means "impossible to solve in the general case using an
algorithm").

Here is a simple example:

int j;
int i = 5;
if(i == 5)
j = 0;
j++;

Here is an example you could not expect any compiler to catch
(assume you have a method to compute the nth digit of pi):

int j;
if(digitOfPI(98000009) == 3)
j = 0;
j++;

-Larry Barowski

When the compiler complains about those cases, it is correct.

Consider the following example:

class S
{
String s;
}

// omitted
myS.s = "blah";

// point X
if(myS.s == "blah")
{
// this is NOT guaranteed to execute
}

If a thread pre-empts at point X and changes the object referred to by myS.s
then the boolean expression may evaluate to false (otherwise, it will
evaluate to true).
It is unreasonable to expect that the compiler should *know that*, in your
case, the int can never be altered by another thread (since it is a
primitive type and cannot be dereferenced), and therefore will evaluate
always to true.

Most JIT compilers will determine that the condition always evaluates to
true (unless it is declared with the volatile keyword to indicate
otherwise), and so will not bother evaluating the expression.

Either way, I'm not convinced that this case was the intended reference.
Unless proven otherwise, I'll maintain that the comment itself was bogus.

--
Tony Morris
(BInfTech, Cert 3 I.T., SCJP[1.4], SCJD)
Software Engineer
IBM Australia - Tivoli Security Software
(2003 VTR1000F)
 
V

Virgil Green

Tony Morris said:
No, it wouldn't contain anything - it would simpyly be uninitialized and
prevented from use.

Java != C

That Java prevents an uninitialized variable from being used is in no way
relevant to what may or may not be present at the location in memory
allocated to said variable prior to initilization. The language specifically
*requires* initialization so the garbage value from having an uninitialized
variable cannot be accessed.

There *must* be some value/state at the memory address. The memory address
doesn't appear out of the ether upon initialization.

- Virgil
 
E

Eric Sosman

Chris said:
I think the wording you've choosen is a bit misleading.

The complaints are "bogus" in the sense that a different analysis with
different rules might have recognised the case.

However they are not "bogus" in the sense of being wrong. There are definite
rules for deciding whether a variable has been intialised before use, those
rules are part of the definition of the Java language, and the compiler follows
them -- it is not allowed any choice. There may be bugs, of course, but I,
personally, don't know of any.

Yes, there are rules for determining whether a variable
might be uninitialized at the point of using it. As far as
I know, the rules are applied correctly (that is, I haven't
encountered a bug).

However, the rules are what a mathematician might call
"Sufficient but not necessary" in that they complain about
non-initialization in situations where it cannot happen.

public static void main(String[] args) {
int x;
if (args.length >= 0)
x = 42;
System.out.println(x);
}

By the properties of arrays, `args.length' cannot be negative,
so `if (args.length >= 0)' is equivalent to `if (true)' and
the `x = 42' assignment will always occur -- but the compiler
complains anyhow. (By the way, there's no complaint if you
actually write `if (true)' -- the compiler is smart enough to
know that `true' is true, but not smart enough to know that
array lengths are non-negative.)

Admittedly, this example is contrived and perhaps even
stupid. That's in the interest of brevity, though: similar
things can occur in more "realistic" code as well.
 
L

Lasse Reichstein Nielsen

Tony Morris said:
When the compiler complains about those cases, it is correct.

No. That code, if executed as the body of a method, would never access
an uninitialized variable. If the compiler could know that, it could
omit the warning. Ofcourse it cannot know, and we are not blaming it
for wanting to be sure before it allows the program.
Consider the following example:

It's another example. Those examples were correct (if the 98000009th
digit of pi is actually 3).

Your example is incomplete, so it's impossible to tell what happens.
In the appropriate context it is quite possible that it would access
some unstated uninitialized variable.
It is unreasonable to expect that the compiler should *know that*, in your
case, the int can never be altered by another thread (since it is a
primitive type and cannot be dereferenced), and therefore will evaluate
always to true.

We are not claiming that the compiler should be able to solve an
undecidable problem. Just saying that some warnings about access to
uninitialized variables are incorrect, because the program would not
access an uninitialized variable if run.
Most JIT compilers will determine that the condition always evaluates to
true (unless it is declared with the volatile keyword to indicate
otherwise), and so will not bother evaluating the expression.

Sure, cases can be decided, but the problem in general is undecidable.
Either way, I'm not convinced that this case was the intended reference.
Unless proven otherwise, I'll maintain that the comment itself was bogus.

That's your right :)

/L
 
L

Larry Barowski

It's another example. Those examples were correct (if the 98000009th
digit of pi is actually 3).

To be precise though, let's assume the method digitOfPI() is static
or final, otherwise it could be overridden by an incorrect
implementation in a subclass.

-Larry Barowski
 

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

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top