1

如何自实例化 Java 类?我不应该使用除其类文件之外的任何文件。还假设在我初始化 NAME 变量的那一行之后,他们在编译时不知道类的名称。

例子:

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

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

将是错误的,因为它需要另一个名为Bar.java. 它应该是:

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

我加入了这个编程挑战网站,每个问题我只能提交一个文件。我想为我将用于挑战的所有类创建一个模板类。所以,我的想法是我会这样做:

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
    }
}

我只想更改类名和 NAME 变量,而不必更改每次使用模板类时实例化类的方式。使用我当前的设置,我将不得不编辑该行:Foo foo = new Foo();也许还有下面的行。

您可能还想知道为什么我必须调用launch()而不是在 main 方法中执行所有操作。这只是我从我的 Java 讲师那里得到的东西。这也是因为我不能在方法中使用非静态方法main()

4

7 回答 7

1

如果你“实现”任何东西,你需要定义一个接口。要么你导入一个已经存在的,要么你必须创建它。无论哪种方式,如果它是公共类(抽象或非抽象)或接口,则必须在单独的文件中定义。与 C++ 不同,这是 Java 要求。

如果:

public class Foo implements Bar { 
} 

那么您的项目必须至少包括:

Foo.java
Bar.java 

时期。没有如果/和/但是。

但是,如果您的项目中绝对必须只有一个文件,则您必须获得一个字节码生成器并在运行时动态构建您的类和接口。

真正的问题是:你想要完成什么?如果它是单例/工厂,其他人已经回答了这个问题。如果是为了减少编译单元的数量,那你就不走运了。Java 强制要求您必须这样做。

作者更新后编辑:

Java 允许您执行以下操作:

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() { } 
}

.... 

这将完成您想要实现的目标。

于 2009-11-04T16:27:15.593 回答
1

您已编辑您的消息并添加了更多信息。那挺好的。现在问题更清楚了。您实际上是在寻找工厂模式。

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");
    }
}

第一个参数显然是类名。希望这可以帮助。

于 2009-11-04T16:48:27.737 回答
1

如果您不打算在其上调用多个方法,为什么要存储引用?

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

在这里,为每个问题更改文件所需要做的就是更改两行:类头和new子句!简单的!

于 2010-08-20T14:55:23.703 回答
0

您需要mainFoo类中调用其构造函数的方法:

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

然后您可以通过可执行文件(它将调用 main 方法)运行该类:java

$> java mypackage.Foo

我不确定您为什么选择实现该Bar接口;从您的问题来看,这似乎是不必要的。

于 2009-11-04T16:16:52.980 回答
0

怎么样?

public class Foo {

    private void instantiate()  {
        Foo foo = Foo.class.newInstance();
    }
    //...
}
于 2009-11-04T16:20:08.213 回答
0

要么在主要方法中做到这一点:

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

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

或作为初始化器:

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

    private void getInstance()  {
        return instance;
    }
}
于 2009-11-04T16:20:21.593 回答
0

这里没有人听说过 Java 中的嵌套/内部类吗?自 JDK 1.2 以来,它们就一直存在,大约 9 年前还是新的。

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!");
        }
    }
}

您可以将类嵌套到基本上任意深度,使用包含类作为模块并包含嵌套类和接口的任意集合。通过包含一个main(String[]),您可以为您的程序提供一个入口点,它可以从该入口点开始。

这种方法将为您提供一个源文件,从中可以生成任意数量的类文件。嵌套类都将具有唯一的名称(与在顶层包含多个非公共类的技巧不同)。

于 2009-11-04T19:37:20.280 回答