Thomas said:
I want to create a class that has all my favorite behavior for headless
applications. I want it to do all the desired stuff when my
applications start-up. We'll call this EfiMain
1 public class EfiMain {
2 public static void main(String argv[]) {
3 EfiMain anEfiMain;
4 // do some startup stuff for my apps.
5 anEfiMain := new EfiMain();
6 anEfiMain.main(argv);
This is broken (as perhaps you know) because it will always invoke
EfiMain.main, even if anEfiMain is actually an instance of an EfiMain
subclass. It also creates an efiMain instance (or, if there were a way
to do what you actually want, a subclass instance) which it then
discards without using. That's right, without using. Invocation of
static methods "on" instances does not actually use the instances at
all, only the compile-time type of the references. That is one reason
why that mode of static method invocation is recommended against by many
experienced programmers, including several in this forum.
7 }
8 }
9
10 public class EfiEcho extends EfiMain {
11 public void main(String argv[]) {
12 System.out.println(argv);
13 }
After compiling both classes if I run "java EfiEcho" how would EfiEcho
ever run since the static main() in EfiMain doesn't know the name of the
subclass to create. It would have to figure that out at runtime.
You are going about it the wrong way. If you run "java EfiEcho" then
EfiEcho.main will always be invoked (first). If you want to run the
superclass' main as well then you can easily do so from the subclass'
main because there you know the name of the superclass. (Example below.)
I suspect the static main() in EfiMain will run because it's not
overridden in EfiEcho, but how would it know that the instance it's
supposed to create is an EfiEcho and not an EfiMain? Looking at the
command line might be one way but that's cheating.
No, if you run "java EfiEcho" then it is EfiEcho.main that is run by the
VM. The existence of EfiMain.main is irrelevant here. Also, you cannot
cheat by looking at the command line because unlike in C / C++ / *NIX
shells, only the arguments to the application (everything _after_ the
class name) are provided in the argument to main(String[]).
I guess I'm looking for a corallary to Smalltalk's "self new" which when
run from a class (static) method will create an instance of whichever
subclass the message was sent to.
This is not possible in Java because static methods only have the
context of their declaring class available. Either through programmer
knowledge or through reflection static methods can use their class'
superclass, but they cannot obtain subclass information either way.
My next question will be about invoking super methods, but I'll read
more of Bruce Eckel's book before asking that.
Here is an example that shows how you might do what you want:
public class EfiMain {
public static void main(String[] args) {
// do common startup stuff
}
}
public class EfiEcho extends EfiMain {
public static void main(String[] args) {
EfiMain.main(args);
// do stuff specific to EfiEcho
}
}
Note that the two classes must be in separate files if, as above, they
are both public. Also note that the above example in no way depends on
EfiEcho being a subclass of EfiMain, or on EfiMain.main's specific name
or signature. If EfiMain is not an application in its own right then
some other name should probably be chosen.
John Bollinger
(e-mail address removed)