How to call an instance method from a static method allowing overrides?

  • Thread starter =?ISO-8859-1?Q?Thomas_Gagn=E9?=
  • Start date
?

=?ISO-8859-1?Q?Thomas_Gagn=E9?=

I'd like to be able to subclass a class with "public static main(String
argv[])" but since static methods can't be overridden I want it first to get
an instance of itself then call the instance's main().

Problem is, how does the class reference itself without naming itself?
 
S

Sandip Chitale

public class ClassName {
// JDK 1.4
static String className = new Throwable().getStackTrace()[0].getClassName();
public static void main(String[] args) {
System.out.println(className);
// now you have class name in static context
// maybe you can use Class.forName() to get the Class and then call methods
// using reflection

}
}
 
T

Tobias Noebel

Hi Thomas,

Thomas Gagné said:
I'd like to be able to subclass a class with "public static main(String
argv[])" but since static methods can't be overridden I want it first to
get an instance of itself then call the instance's main().

Problem is, how does the class reference itself without naming itself?

I hope I understood your problem:
You want to call "java A", but want to extend A with class B, and somehow
get B.main() called (first)?

First of all you can override a static method (as long as it is not final),
the Swing-UI uses this for creating ComponentUIs.

But this doesn't help much in your case, due to the fact, that you call a
static method on a class:
A.main();
And whatever class extends A, because main() is static linked there is no
possibility to get even knowledge from A, which classes are extending A.
Assume there are two classes B and C extending A. How should A (or java)
know, that you mean B.main() instead of C.main()?

On the other hand, if you call "java B", then you can write a new static
main() in class B calling the super main() of class A by A.main(), and it
will work fine.

Tobias Nöbel

p.s. With respect to Sandip, but his suggestion wont work because className
would linked static to ClassName.
 
?

=?ISO-8859-15?Q?Thomas_Gagn=E9?=

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);
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.

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.

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.

My next question will be about invoking super methods, but I'll read more of
Bruce Eckel's book before asking that.
 
K

Karl von Laudermann

Thomas Gagné said:
I'd like to be able to subclass a class with "public static main(String
argv[])" but since static methods can't be overridden I want it first to get
an instance of itself then call the instance's main().

There's no such thing as "the instance's main()". main() belongs to a
class, and has no inherent relationship with any instance of that
class, even when called using an object rather than the class name. In
fact, no such instance even exists when your program starts running.
The only way to "get" an instance of the class is to create one.

I tend to write main() methods that do little more than allocate a new
instance of the containing class, and then call a non-static method on
that instance to do all of the real work. It sounds to me like you
might want to do the same thing here.

class A
{
public static main (String argv[])
{
A myObj = new A();
myObj.doStuff();
}

protected void doStuff()
{
// Actual program implementation
}
}

Now you can have all of your program logic in non-static methods,
which a subclass can override and call from its main() method.
 
R

Roedy Green

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.

There is clone, but it is protected. You have to manually write a
public wrapper for it every time you want to actually use it.

see http://mindprod.com/jgloss/clone.html
 
J

John C. Bollinger

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)
 
T

Tobias Noebel

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);
7 }
8 }
9
10 public class EfiEcho extends EfiMain {
11 public void main(String argv[]) {
12 System.out.println(argv);
13 }


Ok, here is one suggestion:

public class EfiMain {

public static void main(String argv) {
main(new EfiMain(), argv);
}

public static void main(EfiMain mainObject, String[] argv) {
// do some startup stuff for my apps.
anEfiMain.init(argv);
}
public void init(String argv[]) {
// All extra stuff
}

}

public class EfiEcho extends EfiMain {
public static void main(String[] argv) {
main(new EfiEcho(), argv);
}

public void init(String argv[]) {
System.out.println(argv);
}
}


Here is another - better, more Java-like:

public class EfiMain {

public static void main(String argv) {
new EfiMain(argv);
}

public EfiMain(String[] argv) {
// do some startup stuff for my apps.
anEfiMain.init(argv);
}
public void init(String argv[]) {
// All extra, maybe unnecessary stuff
}

}

public class EfiEcho extends EfiMain {

public static void main(String[] argv) {
new EfiEcho(argv);
}

public EfiEcho(String[] argv) {
super(argv);
}

public void init(String argv[]) {
// My extra stuff
System.out.println(argv);
}
}

I hope it's clear why, if not, just ask.

Tobias Noebel
 
?

=?ISO-8859-15?Q?Thomas_Gagn=E9?=

I think I'm straightened out. Thanks.

Tobias Noebel wrote:
Ok, here is one suggestion:

public class EfiMain {

public static void main(String argv) {
main(new EfiMain(), argv);
}

public static void main(EfiMain mainObject, String[] argv) {
// do some startup stuff for my apps.
anEfiMain.init(argv);
}
public void init(String argv[]) {
// All extra stuff
}

}

public class EfiEcho extends EfiMain {
public static void main(String[] argv) {
main(new EfiEcho(), argv);
}

public void init(String argv[]) {
System.out.println(argv);
}
}


Here is another - better, more Java-like:

public class EfiMain {

public static void main(String argv) {
new EfiMain(argv);
}

public EfiMain(String[] argv) {
// do some startup stuff for my apps.
anEfiMain.init(argv);
}
public void init(String argv[]) {
// All extra, maybe unnecessary stuff
}

}

public class EfiEcho extends EfiMain {

public static void main(String[] argv) {
new EfiEcho(argv);
}

public EfiEcho(String[] argv) {
super(argv);
}

public void init(String argv[]) {
// My extra stuff
System.out.println(argv);
}
}

I hope it's clear why, if not, just ask.

Tobias Noebel
 
J

Jezuch

U¿ytkownik Roedy Green napisa³:
static String className = new Throwable().getStackTrace()[0].getClassName();

You can discover the Class corresponding to any object with
dog.getClass(). It works on "this" too with this.getClass().

Won't work in this case because 'this' doesn't exist in static context.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,566
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top