Java 堆栈溢出混乱

Java 堆栈溢出混乱,java,stack-overflow,Java,Stack Overflow,我是一个java新手,对于StackOverflow错误/在类之间访问文件的能力有一个非常令人困惑的问题。我知道根本原因可能是我有一些递归调用,但修复它的语法让我不知所措。我认为这与类如何通过扩展彼此链接有关——但是,如果InputScreen类不扩展ViewController,我就无法访问我需要的方法。我已经将高级代码放在下面(制作一个跟踪汽油里程的程序) 这样做的目的是能够打开一个包含一些历史里程数据的xml文件(使用doOpenAsXML()方法),然后允许用户向一些文本字段(在Inpu

我是一个java新手,对于StackOverflow错误/在类之间访问文件的能力有一个非常令人困惑的问题。我知道根本原因可能是我有一些递归调用,但修复它的语法让我不知所措。我认为这与类如何通过扩展彼此链接有关——但是,如果InputScreen类不扩展ViewController,我就无法访问我需要的方法。我已经将高级代码放在下面(制作一个跟踪汽油里程的程序)

这样做的目的是能够打开一个包含一些历史里程数据的xml文件(使用doOpenAsXML()方法),然后允许用户向一些文本字段(在InputScreen类中定义)添加数据,向ArrayList添加另一个数据点,然后使用doSaveAsXML方法保存

有人对如何使这项工作有想法吗?谢谢


//Simple main只打开一个ViewController窗口
公共级MPG跟踪{
公共静态void main(字符串[]args){
ViewController cl=新的ViewController();
cl.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
cl.setVisible(真实);
}//末端总管
}

公共类ViewController扩展了JFrame{

public ViewController() {
     doOpenAsXML();  // open historical data, put into 'hist'
     InputScreen home = new InputScreen ();
}
//要使用历史数据填充的数组列表
公共ArrayList hist;
公共视图控制器(){
doOpenAsXML();//打开历史数据,放入“hist”
InputScreen home=新的InputScreen();
}
公共void doSaveAsXML(){
//…要以正确的xml格式保存的长块
}
公共空间{
//…要以正确的xml格式打开的长块
}
}

公共类InputScreen扩展了ViewController{ //语句定义带有文本字段和“保存”按钮的屏幕 //语句在“保存”按钮上创建侦听器 //要添加到ArrayList hist的语句,在ViewController方法中打开 doSaveAsXML(); }


您是说InputScreen扩展了ViewController吗?这似乎是构造函数中的无限递归循环。而且

public class ViewController {

    ...

    public ViewController() {
         doOpenAsXML();  // open historical data, put into 'hist'
         InputScreen home = new InputScreen (this); // give myself to our new InputScreen.
         // do something with home
    }

    public void doSaveAsXML() {
    // ...long block to save in correct xml format
    }

    public void doOpenAsXML() {
    // ...long block to open in correct xml format
    }


}

public class InputScreen {

    private ViewController controller;

    public InputScreen(ViewController contr) {
       this.controller = contr;
    }


    void someMethod() {
        // statements to define a screen with text fields and a 'Save' button
        // statements to create a listener on the Save button
        // statements to add to the ArrayList hist, opened in the ViewController method
        controller.doSaveAsXML();
    }
}

什么都不做。您创建了一个新的InputScreen,将其设置为变量home,一旦构造函数完成,它就会立即得到GCD。

这似乎是问题的根本原因:

但是,如果InputScreen类没有扩展ViewController,我就无法访问我需要的方法

要访问另一个类中的(非静态)方法,需要该类的对象。在您的情况下,InputStream需要具有一个ViewController对象,而不是成为一个ViewController对象。(在同一行上,ViewController不应是JFrame,而应具有一个JFrame-尽管这不会带来问题。)

如果你改变这个,你不会得到你的构造函数循环

public interface FileOpener
{
  public void doOpen();
}

public class XMLOpener implements FileOpener
{
  public void doOpen(){ ... do xml specific file opening ... }
}

public interface Stream
{
   /** inits stream with controller     
    **/
   public void init(FileOpener FileOpener);
   public void kickIt();
}

public interface Controller 
{
   // defines other methods implemented by actual interfaces.
   public void kickIt();
}

public class ViewController implements Controller 
{
   private Stream stream;
   private FileOpener opener;

   public ViewController( final Stream stream. final FileOpener opener )
   {
     this.stream = stream;
     this.opener = opener;

     this.stream.init(this.opener);
   }


   public void kickIt(){ stream.kickIt() );
}

public class InputStream implements Stream
{
   private FileOpener opener;

   public InputStream()
   {
   }

   public Stream init(final FileOpener opener )
   {
     this.opener = opener;
   }

   public void kickIt()
   {
     this.opener.doOpen();
   }
}

....

Controller controller = new ViewController( 
      new InputStream(), 
      new XMLOpener() );
简短的回答:

我建议你看了我的帖子后在上面搜索一下;)

首先,您不需要
InputStream
作为
VieController继承
VieController。doSaveAsXML()
是公共的

即使它具有私有的|受保护的|包可见性,我们也不应该只使用继承来访问对我们不可见的其他类上的方法。继承用于继承、细化或扩展行为,而不是访问方法

始终可以将控制器作为参数类型传递给输入流。如果您的输入流需要访问控制器中的所有方法,请按原样传递控制器(或者让控制器实现一个包含其中所有方法的接口)

需要注意的第一件重要事情是,
InputStream
实际上不需要访问控制器。它只需要访问一些可以为它打开
文件的功能-它需要一个
文件开启器

需要注意的第二件重要事情是控制器(通常)也不需要知道如何打开文件。控制器通常是组织者或编排者(因为没有更好的词)。因此,它不需要是文件开启器(或实现文件打开逻辑本身)。控制器只需要对文件开启器的引用。与
输入流一样,
控制器
只需将
文件打开逻辑
委托给
文件打开器

换言之:

  • 您的输入流需要 访问文件开启器
  • 您的控制器也只需要 有权使用文件开启器
  • 您的控制器初始化您的控制器 输入流,因此,它需要 在运行期间向其传递文件开启器 初始化
  • 由于上述原因,控制器 自身需要接受,, 实例化或配置一个 文件开启器本身
  • 因为文件开启器是外部的 流和控制器, 文件开启器应该是一个 接口(可以实现) 通过xml文件开启器或任何开启器 就这点而言。)
  • java伪代码: 无论您是否一直努力使所有内容都与接口处理程序兼容,这都是我们必须在每个项目中做出的设计决策。但这种方法(或受其启发的东西)是典型的发展方向。这种方法很难(但并非不可能)产生周期性依赖,当它们确实发生时,它们是配置问题,而不是对象模型的固有问题


    希望能有所帮助。

    你问题的标题让我一时困惑!今天,我的大脑工作不太正常……使用调试器进入代码,您将看到方法a调用方法B的模式,最终您将进入方法a而不返回。啊,谢谢大家。保罗,非常有帮助-我需要重新思考我是如何组织我的课程的,如何混合
    public interface FileOpener
    {
      public void doOpen();
    }
    
    public class XMLOpener implements FileOpener
    {
      public void doOpen(){ ... do xml specific file opening ... }
    }
    
    public interface Stream
    {
       /** inits stream with controller     
        **/
       public void init(FileOpener FileOpener);
       public void kickIt();
    }
    
    public interface Controller 
    {
       // defines other methods implemented by actual interfaces.
       public void kickIt();
    }
    
    public class ViewController implements Controller 
    {
       private Stream stream;
       private FileOpener opener;
    
       public ViewController( final Stream stream. final FileOpener opener )
       {
         this.stream = stream;
         this.opener = opener;
    
         this.stream.init(this.opener);
       }
    
    
       public void kickIt(){ stream.kickIt() );
    }
    
    public class InputStream implements Stream
    {
       private FileOpener opener;
    
       public InputStream()
       {
       }
    
       public Stream init(final FileOpener opener )
       {
         this.opener = opener;
       }
    
       public void kickIt()
       {
         this.opener.doOpen();
       }
    }
    
    ....
    
    Controller controller = new ViewController( 
          new InputStream(), 
          new XMLOpener() );