In this lab, you will work with reference variables and the NetBeans debugger.
Because variables are used so frequently, they need to be in a place where they can be quickly accessed. The stack provides this place. Each local variable, whether it is a primitive data type or a reference variable, is stored on the stack. When you use a variable's name, the computer quickly locates that variable in memory and retrieves its value.
Physically, the stack is nothing more than a big block of memory. The system handles all the details of managing its size so you don't have to worry about it.
When you call a method, that method is given a portion of memory at the top of the stack to store its local variables and parameters. Because each method uses its own portion of the stack, we know that one method cannot modify the local variables of another methods.
When a method returns (or finishes running), the portion of memory on top of the stack used by that method is freed by the system. In other words, that method's variables no longer exist in memory. The following Stack N' Heap demonstrates this:
Code
{
int myVar = 5; dosomething ( ); System.out.println( myVar ); } public void dosomething ( ) { int myVar = 18; System.out.println( myVar ); } |
Stack
|
Heap
|
Temporary
|
Because methods do not share memory, the only way methods can share information is via return values and parameters. A method can return information to the method that called it using a return value. A method can send information to the method it is calling by giving values to that method's parameters. The following Stack N' Heap demonstrates the use of return values.
All objects are stored on the heap. The system cannot find an object once it is stored on the heap unless it knows its address; an object addresses are stored in reference variables. Although objects that are not referenced by a reference variable are useless, they still take up space in memory. To reclaim this space, a procedure called garbage collection is run. This process scans the heap to find objects that can be removed. The system handles this automatically; you needn't worry about it.
As mentioned above, a method can send information to a called method
by giving values to that method's parameters. A method's
parameters are declared in the parenthesis immediately following the
method's name. The syntax for declaring a parameter is very simple,
it is identical to declaring a variable. For instance:
the method header
public void dosomething (int param1, String param2)
begin a method named
dosomething
that has two parameters:
an integer named param1
, and a
String
reference variable named param2
.
In order to call this method,
you must provide an initial value for each of these parameters, such as
dosomething(5, "This is a test");
.
(Note
that a comma separates the two expressions supplied for the parameters.) The
values "passed" to the method when you call it become the initial
values of that method's parameters.
When you call a method you must specify the initial values of its parameters; these values can be changed as the method runs. Using the assignment operator, you can change the value stored in a parameter, but this will have no effect on the variable stored in the calling method:
Code
{
int myVar = 5; dosomething3 ( myVar ); } public void dosomething3 ( int temp ) { temp = temp + 15; } |
Stack
|
Heap
|
Temporary
|
Remember that reference variables store addresses. When a parameter is a reference variable, it must be given an object's address as its initial value. You can use the assignment operator to change the address stored in a reference parameter. You can also use the address stored in the reference parameter to change the instance variables of the object to which it refers. These changes will exist after the method stops running. The following Stack N' Heap illustrates this:
The file Teacher.java defines a simple class
that represents a Teacher
, an object with a name, a picture, and a
rating. The file References1.java contains a
program that instantiates two Teacher
objects and then makes some
modifications to the objects and their references. Your job is to
complete that program as described in the comments in
References1.java. There are three
modifications that you are asked to make and there is a checkoff below
for each of these three modifications.
However, this is one small task before we get started.
Some of the methods and constructors of Teacher
must be passed filenames containing GIF images.
This prevents a slight problem for the Java system because it must determine the directory containing the GIF image. NetBeans allows you to set your program's working directory to handle this problem, but this takes a bit of work. First, go into the Filesystems pane of the Explorer panel and right-click on the Teacher icon; select Properties from the pop-up window. Now select the Execution tab at the bottom left of the Properties window.
Next, make sure that Executor is set to
External Execution and press on
External Execution. This should cause a box
with three little dots to appear just to the left of
External Execution. Now, double click on the
box with three dots.
The Executor window
should pop-up. Click on the Expert tab in the
right panel. You should now see a table with a cell containing
Working Directory in the lower left corner.
Its partner cell in the lower right corner is blank. Click on the
blank cell and be rewarded with another box of triple dot.
Finally, click on the triple dots.
Now you have the Working Directory pop-up
which you can use to set the directory Java uses for
opening files with relative filenames.
Set this directory to your csci/201/Stack
subdirectory.
If we weren't interested in debugging, we'd be done.
However, we must now set the working directory
for the debugger. So do back to the Execution
panel and this time select the triple dots for
Debugger rather than Executor.
pop-up.
Now set the Working Directory in the Debugger to also be class/201/Stack.
Show your lab instructor your code for swapping reference variables along with the displays of both the original and the "swapped" teachers.
Show your lab instructor your code for swapping the objects' names along with displays of the teachers both before and after "swapping" their names. (Be sure to comment out all other displays.)
Show your lab instructor your code for swapping the objects' ratings along with displays of the teachers both before and after "swapping" their ratings. (Be sure to comment out all other displays.)
Open References2.java and compile and run the program. Now that you've run the program and seen the output, study the code and try to understand what is happening. Wouldn't it be helpful to see the Java code be executed a line at a time? This is something we can do with the debugger.
A debugger can step through your program code one line at a time while you examine the values of your program variables. You can also set a breakpoint on a line of code of your program. Your program executes normally until it reaches the breakpoint at which point the program is halted so that you can examine its variables.
Let's start by setting a breakpoint in the
Reference2
class.
Do this by placing your cursor
anywhere within the line that says:
System.out.println ("Enter a teacher rating...");
Next right click while the cursor remains on the
line of Java code. You should see a new
pulldown menu.
Select Toggle Breakpoint from the menu.
A pink rectangle should now surround the selected line.
Because we have more than one class with a main
method, we're going to choose a specific main class for the debugging project.
This isn't stickly necessary, but it will decrease your chances
of going astray during this lab.
Make this choice by going into the Explorer panel and right clicking on
the Reference2 icon.
In the displayed menu select Tools and then
Set as Project Main Class.
You can start debugging from the Project pull-down menu by selecting Debug Project. or you can just select the Run in Debugger button, .
Your program starts, screen flash, and soon you should see
that the line with the breakpoint now has a green background
and is the target of a little green arrow. Your breakpoint
has been reached.
Be sure that the left panel is displaying the Debugger Window. If not, select the Debugging tab.
At the top of the Debugger Window is a line of nine
icons.
Start by turning off all of these nine selections, so that
your icons display as below. These icons control your view of
your program and its variables. We're going to experiement
with these controls. In the following few paragraphs
turn on and off each icon to see its effect. By the way,
it is possible to have several icons selected simultaneously.
The first icon shows the status of your debugging sessions. If should show that your References2 session has been stopped on a breakpoint. It is unlikely that you will ever intentionally have more than one active debugging session while a student in this course.
The second icon
shows the status of your program's threads.
It is possible to have more than one Java interpreter simultaneously
executing the methods of your program. In fact, multi-threaded
applications are required for interesting multi-media applications
and you have undoubtedly encountered many on the web.
Right now, your application may appear to have only one thread,
but push down on those expanders, and you'll see more.
The third icon shows your call stack. This can be used to determine the series of method calls that were made to reach the breakpoint.
The fourth icon displays the local variables of a active method invocation. It is possible, though rarely advisable, to change the value of a variable in this display. Because an object may be passed between method, it may appear in many different method invocations.
The debugger may be working on several sessions.
Each session may be executed by several threads, each with its own
call stack.
Each call stack may have several method invocations, each with its
own set of local variables.
The fifth icon, called All in One, puts this entire
hierarchy into a single display.
Press the expanders in the All in One window to
descend to the depths of your Java program.
The sixth icon controls watches. A watch is a variable the debugger is actively tracking. This used with a programmer thinks a particular variable is causing problems and requires special attention. The value of that variable is displayed in the watch list.
The seventh icon allows you to lists the fields, constructors, and methods of your active classes. Many classes are within packages and you must descent through the class hierarchy to uncover them. Press the Classes icon. Notice that the class Teacher is not displayed. That's because your program has yet to instantiate an object of class Teacher.
The eighth icon provides a quick list of breakpoints.
The ninth icon is for properties, a mechanism for internationalizing the text displayed by a Java application. You won't use them here.
When you reach a breakpoint, you can start stepping through the code. For each line of code, you can either:
Presumably your debugger is still waiting at the breakpoint. Go into the Local Variables view where you should see nothing put a single variable args.
Contine to step over lines of code until the first call to the
zeroRating() method is highlighted. By now,
you should have a teacher reference variable
in the local variables display. Click the expander to
teacher to view its instance variables.
Note
that some of the instance variables are also references to objects
that can be viewed. Explore all reference variables and make sure
that you understand what you see.
Now use the Step Into button, or the
F7 key, to step into the
zeroRating() method. Display both the call stack and
local variables windows and switch between the two sets of local
variables by choosing between the two frames of the call stack. You
choose a frame by double-clicking on that frame in the call stack.
Advance to the "}" marking the end of the zeroRating() method.
Show your lab instructor the variables in both zeroRating()
and main()
. Explain why the value of rating
in main()
is not changed by the call to
zeroRating()
.
Advance until the second call to zeroRating()
is highlighted,
and then step in to zeroRating()
. Again, observe the
call stack and local variables display. Click
the expander to view the object referenced by the
argument inputTeacher
.
Advance to the "}
" marking the end of this
zeroRating()
method.
Show your lab instructor the variables in both zeroRating()
and main()
. Explain why the Teacher
object created in main()
is
changed by the call to zeroRating()
.