Java for Fortran Programmers: Part IV

[[ Thanks to Lee Higbie of ARSC for this tutorial. ]]

The topic today is:
- HelloBill, a simple Java GUI program

Here is the full text of HelloBill.java. The line numbers are not part of the code but were inserted here to facilitate discussing the code. I have deleted most blank lines to keep the length low in the newsletter. Also, in a text newsletter, the best way to describe a program appears to be with embedded comments and notes about specific lines at the end. That's where mine are.

Notes on HelloBill.java: Because the class is named HelloBill, the file must be named HelloBill.java. The name is case sensitive, even on Windows systems.

Lines 8, 9:
Most classes start with a series of import statements. As described in Chapter 3, these allow referencing the classes in those packages by the class names. The AWT includes a complete set of basic widgets. The widgets are in the java.awt package and the events are in java.awt.event. Notice that the import on line 8 does not import the events. The wild card only says to import all the members of the java.awt package.

Line 11:
The extends clause means that HelloBill is a subclass of Frame (java.awt.Frame) and thus has access to all its public and protected methods, variables, ...

Line 12:
The implements clause implies a contract between HelloBill and Java saying that HelloBill will have all the methods of the implemented classes. Java does not permit multiple inheritance (a class can extend only one other class) but the implementing capability allows a class to take on attributes of many others. More about this much later.

Lines 15, 16:
Because title is static there is only one title for the HelloBill, no matter how many HelloBill objects are created. If many instances of HelloBill were created, many HelloBill objects, each would have its own disposeBtn because this variable is not static. The keyword "new" says create an object. In this case it calls the (object) constructor for Button that has one argument, a String.

Line 19:
When you run the Java interpreter, java, it starts your application at the first method it finds that is public, static, void (no return value), is called "main" and accepts a single parameter that is an array of Strings. In general, method calls are by the complete signature: the name + the classes of the arguments + the order of the arguments. In this case java passes the command line arguments to main as a String [ ]. Executing java HelloBill Amy Pam will cause java to pass an array of two Strings to HelloBill.main, the main method in the class.

Line 20:
One of the field variables of Array objects is length = number of elements in the array. Because Java will not allow reference with an out-of-range subscript, the program must have the test for the number of arguments. Comment the test (insert // at the beginning), recompile and rerun with no command line argument and the program will fail with:

Line 26:
The keyword "new" causes the creation of an object, a HelloBill object in this case. In particular, it calls a constructor for the HelloBill class.

Line 29:
When a method specifies no result type and has the same name as the class, it is a constructor for the class. Whenever "new HelloBill" is called with a single string as the parameter, a HelloBill object will be created. As with any other method, there can be many public HelloBill methods with different signatures.

Line 30:
The keyword super indicates the parent class, the class that this class extends. In other words, super(t) call the constructor for Frame that has a single string as its argument, which creates a frame with t on the title bar.

Lines 30-34:
The comments describe their meaning.

Lines 37-42:
This method is required by the implements ActionListener contract. A mouse click on a button will create an ActionEvent and this method will be executed.

Lines 44-53:
These methods are required by the implements WindowListener contract. A mouse click on a title bar widgets will generate a WindowEvent and a call to one of these methods. You can put print statements into the code to see when they respond. You can also comment out line 46, the System.exit(0) call, and the kill button on the title bar of your HelloBill will no longer work. You will continue to see the result of the print statement so you know the interrupt is being received by your method.

Print statements send their output to the "java console," the terminal window where you execute the java <class name> command.

To play with this yourself, copy the code to a code editor, cut out the line numbers and save as HelloBill.java. Then, in the directory where you saved it, type javac HelloBill.java to compile the program. The compilation will produce a class file, HelloBill.class. To run the program you then type java HelloBill (case sensitive, remember). Note that the java compiler is javac, with a c on the end and the java program runner is just the word java.

Quick-Tip Q & A

A:[[ I use the Unix system call:
[[
[[ int getgroups (int gidsetlen, gid_t *gidset)
[[
[[ This stores a list of values of type gid_t into the simple,
[[ C-style array, gidset. However, I'm using C++, and want to use
[[ the vector container class from the Standard Template Library to
[[ operate on the list.
[[
[[ Generalizing the question, what's the best way to copy a simple
[[ array into an STL vector object? Is this as good as it gets?
[[
[[ for (int i = 0; i &lt; numberOfArrayElements; i++)
[[ {
[[ theVector.push_back ( theArray[i] );
[[ }
#
# Thanks to Rich Griswold:
#
The memory for an STL vector is guaranteed to be contiguous, so you
can do something like this:
typedef std::vector<gid_t> gid_array_type;
int gidsetlen = getgroups( 0, NULL );
if ( -1 == gidsetlen ) { return false; }
gid_array_type gids( gidsetlen ); // Allocates memory to hold IDs
if ( -1 == getgroups( gidsetlen, &gids[0] ) ) { return false; }
If you've already declared your STL vector, you can allocate the
memory by calling:
gids.reserve( gidsetlen );
If you already have the data in a C array called gidset, you can do
this (after allocating the memory in the STL vector):
memcpy( &gids[0], getset, gidsetlen * sizeof( gid_t ) );
#
# Here's further discussion from Rich, which he generously provided
# on our request:
#
The original STL standard was ambiguous concerning the question
of whether the memory allocated for a vector will be contiguous,
but that has been fixed. Taking the address of the zeroth element
will return the address of the beginning of the allocated memory,
so I haven't seen anything recently that seriously discourages this
practice. Before the standard was updated, some people discouraged
it, since theoretically some implementation might use non-contiguous
memory, but to my knowledge, no implementation actually did this.
There are a few possible gotchas. First, like C, you have to make
sure the memory is actually allocated. You can use either of the
two methods, either through the constructor, or with reserve().
To check if the memory is actually allocated, use capacity().
Second, I usually use typedefs with STL containers, since it
makes code developement easier by reducing the amount of typing.
For example, instead of typing:
std::vector<std::string> strings;
std::vector<std::string>::iterator itr;
I can type "typedef std::vector<std::string> strings_type;" once,
then use it throughout my code:
strings_type strings; strings_type::iterator itr;
This becomes more important when you start nesting types like this:
std::map< std::map::size_type, std::vector<std::string> > foo;
It also makes maintenance eaiser, because you can just change the
typedef in one place if you need to make a change; for example from
std::vector to std::list. This is where the second gotcha comes in.
If you are using a std::vector in a typedef, and you change it to
another container type that does not guarantee contiguous memory
allocation, code that depends on contiguous memory will break.
As long as you keep this in mind, there isn't any problem I know of
with using STL vectors in place of C arrays in this way.
#
# And a response from Co-editor, Don Bahls
#
Instead of copying element by element, you can use the assign
operator:
theVector.assign(theArray,theArray + numberOfArrayElements);
The first operand is a pointer to the start of the array. The second
is a pointer past the last element of the array. If you use this
method make sure you declare "theVector" to be a container of the
same type as "theArray". E.g.,
std::vector<gid_t> theVector;
Q: I use ScaLAPACK, therefore I use BLACS. I'm on AIX, therefore I use
ESSL/PESSL. I don't use MPI. Here's my question:
I need the global minimim value of a distributed matrix. SHMEM provides
a routine to determine this:
shmem_double_min_to_all :
"Performs a minimum reduction on array of doubles"
I don't see anything in ScaLAPACK and the routine provided in the
BLACS library is no help:
DGAMN2D:
"Perform an elementwise absolute value max/min." ... "Remember, ...
The absolute value is used to determine the max/min."
Suggestions?

The University of Alaska Fairbanks is an affirmative action/equal
opportunity employer and educational institution and is a part of the University
of Alaska system.
Arctic Region Supercomputing Center (ARSC) |PO Box 756020, Fairbanks, AK 99775 | voice: 907-450-8602 | fax: 907-450-8601 | Supporting high performance computational research in science and engineering with emphasis on high latitudes and the arctic.
For questions or comments regarding this website, contact info@arsc.edu