You can subscribe from our home page:
http://www.javaspecialists.co.za (which also hosts all previous issues,
available free of charge
This free advanced Java newsletter is wholly funded by
Maximum Solutions, your partner in Object Orientation and Java. How can we help
you in
your project? Heinz
Welcome to the second "The Java(tm) Specialists' Newsletter", a low-volume
newsletter that is aimed at in-the-trenches Java programmers and those
interested in what the trenches look like nowadays. According to the latest
Computing SA, the e-commerce industry in South Africa is struggling to take off
because it is almost impossible to find Java programmers with any real
experience. Germany seems to be experiencing a similar trend so they want to
import 30'000 Indians. Aren't we working in an exciting segment of the IT
market? I'm so glad I was too jung to try cash in on Y2K bugs and instead
invested my time learning more of Java.
You are either on my mailing list because you begged to be added or because
you did not beg to be removed, in either case, I hope you are enjoying reading
this information and that it will be of benefit to you. Please let me know if
there are topics that you would like discussed or if you would like to share
some of your own experiences through this newsletter. This newsletter is
distributed free of charge to anyone interested, so please forward it to friends
and colleagues who might find the information in this newsletter useful.
In the last newsletter I mentioned in the non-kosher section that Java makes
provision for more than one GUI thread to be in the system and that I did not
know if/when this feature was used. So far I have not found out what the purpose
of this is or if it is still used, although I suspect it's a leftover from the
Awful Windows Toolkit. Do we have a Swing expert in the house?
Anonymous Inner Classes
A feature that we did not have in the early days of Java, when all you needed
to run the VM was a 80386 with 4 MB RAM and a correctly set CLASSPATH, was the
concept of the inner class, specifically the anonymous inner class (heck, we
didn't need that newly-fangled fancy stuff then - we were real programmers .
Inner classes have made it possible to code with less lines and in the process
to obscure the code to the unenlightened but make it wonderfully elegant to
those who understand. A good friend and colleague told me "One good Java
programmer is better than ten bad Java programmers" which I wholeheartedly
agreed with. He then went on to say "And five bad Java programmers are better
than ten bad Java programmers". Inner classes have widened this divide. The
typical way of using anonymous inner classes is for writing GUI event handlers,
e.g.
button.addActionListener(new ActionListener() {
// This is how you define an anonymous inner classpublic void actionPerformed(ActionEvent e) {
System.out.println("The button was pressed!");
}
});
The amazing thing is that we are actually defining a new class(!) while
calling another method. You can virtually make new classes in all sorts of
places in Java. All of this is old hat to most of you, but last week I found a
new application of anonymous inner classes that I had not thought of before. But
first a diversion:
A lot of books seem to suggest that if you want to create a Thread in the
middle of your code you do it as shown in this code. The example is typically
known as an "idiot counter", patented by Microsoft , in which they make the
user dream that progress is happening by changing the screen output in some
way..... (I have used this technique quite successfully in the past)
new Thread(new Runnable() {
public void run() {
try {
while (true) {
sleep(1000); System.out.print(".");
}
}
catch(InterruptedException ex) {}
}
}).start();
If we look at the definition of Thread we see that it takes a Runnable as a
parameter so it sort-of makes sense to create an anonymous inner class from
Runnable and stick that into the parameter. However, looking more carefully
inside Thread we notice that the run() method defined in Thread calls the run()
method defined in Runnable, if a Runnable has been passed into the Thread
constructor. Instead, it would be more efficient to do the following, because we
would have one less object on the heap and one less method call per Thread
creation:
new Thread() {
public void run() {
try {
while (true) {
sleep(1000); System.out.print(".");
}
}
catch(InterruptedException ex) {}
}
}).start();
This way Thread itself is made into an anonymous inner class and we override
the run() method so instead of Thread.run() having to check that a Runnable
exists we can just execute the code in run(). It is a very small difference and
I don't know why I have not seen it used before, but I suspect one of the early
Java 1.1 lemmings jumped over the cliff holding a placard containing the
Runnable as a parameter and all the other lemmings followed the sign To me
the difference is more conceptual than actual and leads me on to the next
application of inner classes:
Anyway, I now get to the real reason for another newsletter, which is an
application of anonymous inner classes which I find quite useful. In Java 1.0,
when we had to pass an array as a parameter to a method we did it as follows:
In Java 1.1, SUN sneaked in a new construct so we would not need to have a
temporary variable, which according to the Refactoring folklore is bad. Since
JDK 1.1 we could thus say:
universityRegistration.addNames(
new String[] { "Heinz", "John", "Anton" });
If you wanted to pass in a Collection instead of an array it would look as
follows:
Collection temp_names = new Vector(3);
temp_names.add("Heinz");
temp_names.add("John");
temp_names.add("Anton");
universityRegistration.addNames(temp_names);
The ability to avoid local temporary variables with arrays was always a
strong deciding factor in defining interfaces to my classes because I could get
away with one line of code instead of five, and the less lines of code the
better. I would therefore rather define
addNames(String[] names) than
addNames(Collection names) even if it meant I would have to convert
backwards and forwards between arrays and collections. However, with anonymous
inner classes we can get the same effect seen above but with collections:
How does work? Very simple, say we wanted to extend Vector with our own
Vector, called MyVector, that contains the three elements "Heinz", "John",
"Anton":
public class MyVector extends Vector {
public MyVector() {
super(3); // to initialise it with a size of 3
add("Heinz"); add("John"); add("Anton");
}
}
The call to the super constructor always happens first, so we could re-write
MyVector as follows without changing the functionality in any way:
public class MyVector extends Vector {
{ // initializer block
add("Heinz"); add("John"); add("Anton");
}
public MyVector() {
super(3); // to initialise it with a size of 3
}
}
If we want to make an instance of an anonymous inner class we can pass the
parameters directly to the super class via the parameter list of the constructor
of the anonymous class. In addition, any init block denoted by {} is done AFTER
the call to the super class constructor is completed, so the class MyVector
could look like this:
Vector myVector =
new Vector(3) { // defining anonymous inner class
{
add("Heinz"); add("John"); add("Anton");
}
};
From here the step to
addNames(new Vector(3) {{ add("Heinz"); add("John"); add("Anton"); }});
is quite simple, I've just removed the comment and bunched the curly brackets
together.
The thing that amazes me most about this "discovery" is that it is such an
obvious thing to do if you have to pass a collection into a method and you know
the size and elements of the collection, but in 3.5 years of Java I'd never
thought of it, and I bet it does not occur anywhere in the 570'000 lines of JDK
1.3 code or the mega-project I worked on in South Africa.
---
Warning Advanced:
When you access private data members of the outer class, the JDK compiler
creates package-access member functions in the outer class for the inner class
to access the private members. This firstly leaves a security hole, although all
data members in Java are public to the initiated , and secondly used to
impede performance before hotspot came along. So, if you are writing code that
has to run reasonably well on non-hotspot code it would be better for
performance reasons to make data members accessed by inner classes
package-access.
---
As always, I welcome your comments and thank you for the positive feedback
from last week.
With regards
Heinz
Copyright 2000-2003 Maximum Solutions, South Africa
Reprint Rights. Copyright subsists in all the material
included in this email, but you may freely share the entire email with anyone
you feel may be interested, and you may reprint excerpts both online and offline
provided that you acknowledge the source as follows: This material from The
Java(tm) Specialists' Newsletter by Maximum Solutions (South Africa). Please
contact Maximum Solutions for
more information.
Java and Sun are trademarks or registered trademarks of Sun Microsystems,
Inc. in the United States and other countries. Maximum Solutions
All logos and trademarks in this site are property of their respective owner. The comments are property of their posters, all the rest 1999-2006 by Java FAQs Daily Tips.