Java Reference
In-Depth Information
Stacks are known as
last-in, first-out (LIFO) data structures
—the
last
item pushed onto
the stack is the
first
item popped from the stack.
When a program
calls
a method, the called method must know how to
return
to its
caller, so the
return address
of the calling method is
pushed
onto the
method-call stack
. If
a series of method calls occurs, the successive return addresses are pushed onto the stack in
last-in, first-out order so that each method can return to its caller.
The method-call stack also contains the memory for the
local variables
(including the
method parameters) used in each invocation of a method during a program's execution.
This data, stored as a portion of the method-call stack, is known as the
stack frame
(or
activation record
) of the method call. When a method call is made, the stack frame for
that method call is
pushed
onto the method-call stack. When the method returns to its
caller, the stack frame for this method call is
popped
off the stack and those local variables
are no longer known to the program. If a local variable holding a reference to an object is
the only variable in the program with a reference to that object, then, when the stack frame
containing that local variable is popped off the stack, the object can no longer be accessed
by the program and will eventually be deleted from memory by the JVM during
garbage
collection
, which we discuss in Section 8.10.
Of course, a computer's memory is finite, so only a certain amount can be used to
store stack frames on the method-call stack. If more method calls occur than can have their
stack frames stored, an error known as a
stack overflow
occurs—we'll talk more about this
in Chapter 11, Exception Handling: A Deeper Look.
Another important feature of method calls is
argument promotion
—converting an
argu-
ment's value
, if possible, to the type that the method expects to receive in its corresponding
parameter
. For example, a program can call
Math
method
sqrt
with an
int
argument even
though a
double
argument is expected. The statement
System.out.println(Math.sqrt(
4
));
correctly evaluates
Math.sqrt(4)
and prints the value
2.0
. The method declaration's pa-
rameter list causes Java to convert the
int
value
4
to the
double
value
4.0
before
passing
the value to method
sqrt
. Such conversions may lead to compilation errors if Java's
pro-
motion rules
are not satisfied. These rules specify which conversions are allowed—that is,
which ones can be performed
without losing data
. In the
sqrt
example above, an
int
is
converted to a
double
without changing its value. However, converting a
double
to an
int
truncates
the fractional part of the
double
value—thus, part of the value is lost. Converting
large integer types to small integer types (e.g.,
long
to
int
, or
int
to
short
) may also result
in changed values.
The promotion rules apply to expressions containing values of two or more primitive
types and to primitive-type values passed as arguments to methods. Each value is pro-
moted to the “highest” type in the expression. Actually, the expression uses a
temporary
copy
of each value—the types of the original values remain unchanged. Figure 6.4 lists the
primitive types and the types to which each can be promoted. The valid promotions for a
given type are always to a type higher in the table. For example, an
int
can be promoted
to the higher types
long
,
float
and
double
.