views:

323

answers:

8

How do I self-instantiate a Java class? I should not use any file other than its class file. Also assume that after the line where I initialized the NAME variable, they don't know the name of the class during compile-time.

Example:

public class Foo implements Bar {
    public static final String NAME = "Foo";

    private void instantiate()  {
        Bar baz = (Bar)Class.forName(NAME).newInstance();
    }
    //...
}

would be wrong since it needs to have another file called Bar.java. It should be:

public class Foo {
    /*
    Instantiate self...
    */
}

I joined this programming challenges website where I am only allowed to submit one file per problem. I want to create a template class for all the classes that I'll be using for the challenges. So, what I have in mind is that I'll do this:

public class Foo {
    public static final String NAME = "Foo";


    public static void main (String[] args) throws IOException {
        //Instantiate self and call launch(args)
        Foo foo = new Foo();
        foo.launch(args);
        System.exit(0);
    }

    public void launch(String[] args) {
        //...Do actual code here
    }
}

I want to only change the class name and the NAME variable and not have to change the way I instantiate the class everytime I use the template class. With the current setup I have, I'll have to edit the line: Foo foo = new Foo(); and maybe the line below that.

You might also be wondering why I have to call launch() and not do everything inside the main method. That's just something I got from my Java instructor. It's also since I can't use non-static methods inside the main() method.

A: 

You need a main method within your Foo class which invokes its constructor:

public static void main(String[] args) {
    Foo f = new Foo(); //the new syntax uses a Constructor, not reflection
    //etc

Then you can run the class via the java executable (which will call the main method):

$> java mypackage.Foo

I'm not sure about why you have chosen to implement the Bar interface; this seems unnecessary from your question.

oxbow_lakes
A: 

How about?

public class Foo {

    private void instantiate()  {
        Foo foo = Foo.class.newInstance();
    }
    //...
}
NawaMan
A: 

Either to do it in the main method:

public class Foo implements Bar {
    public static final String NAME = "Foo";

    public static void main(String[] args) {
        Foo f = new Foo();
    }

Or as an initializer:

public class Foo implements Bar {
    public static final String NAME = "Foo";
    private static final instance = new Foo();

    private void getInstance()  {
        return instance;
    }
}
Rontologist
A: 

If I understand what you're asking, you can do it as a singleton:

public class Foo implements Bar
{
    private static final Bar instance = new Foo();

    private Foo()
    {
        // do stuff
    }
}
Matt Ball
+1  A: 

If you "implement" anything, you NEED to have an interface defined. Either you import one that already exists, or you have to create it. Either way, if it's a public class (abstract or not) or an interface, it MUST be defined in a separate file. Unlike C++, this is a java requirement.

If:

public class Foo implements Bar { 
}

then your project must be comprised of at least:

Foo.java
Bar.java

Period. No ifs/ands/buts.

But if you absolutely must have only one file in your project, you'll have to get a byte-code generator and build your class and interfaces dynamically at runtime.

The real question is: what are you trying to accomplish? If it's a Singleton/Factory, others have answered that already. If it's to reduce the number of compilation units, then you're out of luck. Java enforces the requirement that you have to do it this way.

EDIT AFTER AUTHOR UPDATES:

Java lets you do things like so:

Foo.java:

public class Foo { 
  public static void main(String[] args) { 
    Bar bar = new Bar(); 
  }
}
class Bar { 
   int bar_var; 
   Snafu fu = new Snafu(); 

   public Bar() {  } 
   public int getBarVar() { return bar_var; } 
} 
class Snafu { 
   int var; 
   public Snafu() { } 
}

....

Which would accomplish what you want to achieve.

Chris Kaminski
You know that *inner and nested clases* have been around for at least 9 years, don't you?
bendin
I do, but I can't make that same assumption about him, and why confuse him. inner and nested classes look HORRIBLE, and I use them very sparingly - pretty much only when I have anonymous classes (JButton actions, for example). But thanks for thinking of me. :-)
Chris Kaminski
+1  A: 

You have edited your message and added more info. That's good. Now the problem is more clear. You're actually looking for the factory pattern.

public abstract class Batch {
    public static void main(String[] args) throws Exception {
        Batch batch = (Batch) Class.forName(args[0]).newInstance();
        batch.run();
    }

    abstract void run();
}

class Foo extends Batch {
    public void run() {
        System.out.println("Executing Foo");
    }
}

class Bar extends Batch {
    public void run() {
        System.out.println("Executing Bar");
    }
}

First argument is obviously the class name. Hope this helps.

BalusC
The site gives a certain filename to name the class/file for every problem. So problem 1 might be named School.java then the second problem would be named another thing, so that'll mean editing the `Batch batch = ...` line again. I maybe over complicating things and if what I'm doing is not worth it, I may just have to use the simple `Foo foo = new Foo();` and use my editor's search-and-replace function.
Ramon Marco Navarro
Well, the customer is the king. Live with it ;)
BalusC
A: 

Has no one here ever heard of nested/inner classes in Java? They've been around since JDK 1.2, which was new about 9 years ago.

public class Main {
    public static void main(String[] args) {
        Bar b = new Foo();
        b.doSomethingExciting();
    }
    interface Bar {
        void doSomethingExciting();
    }
    static class Foo implements Bar {
        public void doSomethingExciting() {
            System.out.println("Boo!");
        }
    }
}

You can nest your classes to essentially arbitrary depth, using the containing class as a Module and contain an arbitrary collection of nested classes and interfaces. By including a main(String[]) you provide an entry point for your program from which it can start.

This approach will give you one source file from which any number of class files may be generated. The nested classes will all have unique names (unlike the hack of including multiple non-public classes at the top level).

bendin
A: 

Why store a reference if you're not going to call more than one method on it?

public class Foo {
  public static void main(String[] args){
    new Foo().launch(args);
  }
  public void launch(String[] args){
    //...
  }
}

Here, all you need to do to change the file for each problem is change two lines: the class header, and the new clause! Easy!

Richard Copperwaite