【问题标题】:Working with multiple Classes. Program won't launch使用多个类。程序不会启动
【发布时间】:2013-05-16 01:57:49
【问题描述】:

我一直在处理一个相当大的程序,并认为是时候拆分我的课程了。 1 个用于 GUI 代码的 .java 文件,以及 1 个用于 GUI 呈现的功能背后的机制的 .java 文件。但这是我的问题,我在彼此内部创建了每个类的实例,然后程序拒绝启动,所以我显然做错了什么。在我的RPG 类中,我有以下代码行:

public Mechanics mechanics = new Mechanics();

对于我的Mechanics 课程,我有这个代码:

public RPG rpg = new RPG();

我这样做的原因是为了尝试这个: 我的很多变量都在RPG 类中,我希望能够从我的rpg 调用它们并对其进行操作,然后将它们发送回RPG 这是我用来测试这个函数的代码(来自我的Mechanics 班级):

class Mechanics{
public RPG rpg = new RPG();
  public Mechanics(){
  }
  public void helloWorld(){
    System.out.println("Hello World!");
    System.out.println("Health before:"+rpg.Health);
    rpg.Health = rpg.Health - 5;
    System.out.println("Health after:"+rpg.Health);
  }
 }

是的,Health 是我的 RPG 类中的公共 int

在我的RPG 课程中,这是我用来测试我的Mechanics 课程的代码:

mechanics.helloWorld();

这是我的问题:代码可以编译,但是当我尝试运行它时,我得到了这个错误:

 at Mechanics.<init>(Mechanics.java:15)
 at RPG.<init>(RPG.java:127)

这是我的问题。我这样做对吗?我的代码有什么问题导致我的程序不想运行?

添加:我也尝试将我的其他类称为private,程序将编译,但仍然拒绝启动,并给我同样的错误

Mechanics 的第 15 行:

public RPG rpg = new RPG();

RPG 的第 127 行:

public Mechanics mechanics = new Mechanics();

【问题讨论】:

  • 你能告诉我们完整的堆栈跟踪吗?您似乎没有包含异常的名称。
  • 这就是控制台提供给我的所有内容,我将添加一个图像来帮助你们。我什至滚动到控制台的顶部,这就是它所说的全部
  • 如果错过了异常的名称,那么错误一定是一个损坏的 java/eclipse 文件。也许 jvm 出了问题。
  • 啊,如果我见过一个堆栈溢出的话!
  • 您还可以向我们展示 Mechanics.java 中第 15 行的内容以及 RPG.java 中第 127 行的内容。

标签: java class variables public


【解决方案1】:

这是因为您在 RPG 类中实例化了一个新的 Mechanics 类。然后在Mechanics 类中实例化一个新的RPG 类。

结果是无限循环的实例化。

对于您的具体示例,我个人认为解决问题的最佳方法是将 RPG 实例直接传递给 hello world 方法。

class Mechanics {
    public void helloWorld(RPG rpg) {
        ...
    }
}

然后在你的 RPG 类中看起来像这样:

class RPG {
    // passing a mechanics object in via the constructor would be better than hard-coding it here
    public Mechanics mechanics = new Mechanics();

    public int Health = 100;
    ...

    public void someMethod() {
        mechanics.helloWorld(this); // pass in the rpg instance
    }
}

【讨论】:

  • 给他一个修复它的提示?也许是依赖注入?
  • 有办法解决这个问题吗?我需要两个文件才能相互通信。这就是为什么我可以减少 ONE 源文件中的行数并保持井井有条的原因。
  • @user2388169 通常,您所做的是预先创建尽可能多的“重要”对象,它们实际上做任何事情之前。然后将它们作为构造函数参数或通过设置属性相互传递。只有这样你才能启动程序本身。一般来说,对象自己创建“合作者”(需要长时间保持的其他对象)被认为是一种不好的做法。
  • @user2388169 最简单的前进方式,为您的 RPG 和 Mechanics 成员变量使用 setter 而不是 new。然后从外面“连接起来”。
  • @RichardTingle 是的,当然,如果可以完全避免循环依赖,那就更好了。
【解决方案2】:

Mechanics 的第 15 行可能更像:

public RPG rpg = new RPG(this); // must be in constructor or non static method

在 RPG 中:

public Mechanics mechanics;

在构造函数中:

this.mechanics = mechanics;

【讨论】:

  • 我可以在任意数量的新构造函数或方法中调用RPG rpg = new RPG();吗?
  • 这实际上解决了我的问题并大声运行我的程序。如果需要,我现在可以从任一类调用变量,并根据需要使用它们。
  • 很高兴你把它整理好了。 :)
  • @user2388169 好吧,取决于。你需要有多个RPG 对象吗?如果没有,那么只需创建一个并一劳永逸地连接它。如果是这样,那么您是否需要他们每个人都有自己的 Mechanics 对象副本?如果您可以共享Mechanics 对象,请通过某种工厂 创建RPG 对象而不是直接调用构造函数,并将共享副本传递给构造函数。如果您无法共享Mechanics,则一个对象可以创建另一个对象,但是您应该确定哪个是“所有者”并处理创建其依赖项。
  • @user2388169 一般来说,使用对象工厂之类的东西看起来有点矫枉过正和“企业化”,但好处是它给了你一个回答设计问题的地方,比如“可能存在多少个 X?”,和“哪个 X 应该连接到哪个 Y?”,并将这些答案保留在 XY 的实施之外,这在理想情况下应该只做他们的目的,而不是担心彼此之间的关系,除了事实是这样的关系存在并且“其他人”会照顾它。
【解决方案3】:

在初始化 RPG 或 Mechanics 的实例时会产生无限循环。面向对象编程意味着关注点分离和低耦合。更改您的类依赖项,以便其中只有一个需要另一个。

【讨论】:

  • 有没有办法让两个班级互相交谈?我真的很想为 GUI 制作 1 class,为程序的力学制作 1 class。但是有JLabelsJButtonsJTextAreas我需要从GUI更新Class
  • @user2388169,您可能希望在核心生成事件并将事件发送到 gui 时使用事件处理模型,反之亦然。
  • 所以我可以制作我的 GUI,然后调用我的 Mechanics 类,然后将结果添加到事件和所有内容中?这样会容易很多吗?
  • 您应该花一些时间阅读有关programming patterns 的信息。也很有趣:stackoverflow.com/questions/382623/…
【解决方案4】:

“我已经在彼此内部创建了每个类的实例”

这是你的问题,最终结果是这样的:

A 类被构造,它里面有一个 B 类,它创建了一个新的 B 类
构造了 B 类,其中有一个 A 类,它创建了一个新的 A 类
构造了 A 类,其中有一个 B 类,它创建了一个新的 B 类
构造了 B 类,其中有一个 A 类,它创建了一个新的 A 类
构造了 A 类,其中有一个 B 类,它创建了一个新的 B 类
构造了 B 类,其中有一个 A 类,它创建了一个新的 A 类

等等等等,越来越深,直到你的程序崩溃。

class A 有一个 referenceclass Bclass B 有一个 referenceclass A 没有任何(可怕)错误(尽管它可能没有是理想的),但是 class A 封装 class Bclass B 封装 class A 有一些可怕的错误。如果两者都相互引用,那么对一个或两个的引用将被传递到一个或两个的构造函数中,因此不使用 new 关键字(但如果可能,请避免这样做)。

我经常(内疚地)使用的一个例子如下:

public class OwnerClass {
    SubordinateClass subOrdinate;

    public OwnerClass(){
        subOrdinate=new SubordinateClass(this);
    }

}

public class SubordinateClass {
    OwnerClass owner;

    public SubordinateClass(OwnerClass owner){
        this.owner=owner;
    }
}

免责声明:我并不是将此作为一种好的做法,假设 A 类必须与 B 类对话,反之亦然,那么这就实现了

【讨论】:

  • 电脑不需要死机;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多