Помощь при ошибке переполнения стека?

#java #stack-overflow

#java #переполнение стека

Вопрос:

Вот ошибка, которую я получаю:

 java.lang.StackOverflowError
    at apple.awt.CGraphicsDevice.getScreenInsets(Native Method)
    at apple.awt.CGraphicsDevice.getScreenInsets(CGraphicsDevice.java:673)
    at apple.awt.CToolkit.getScreenInsets(CToolkit.java:741)
    at java.awt.Window.init(Window.java:394)
    at java.awt.Window.<init>(Window.java:432)
    at java.awt.Frame.<init>(Frame.java:403)
    at java.awt.Frame.<init>(Frame.java:368)
    at javax.swing.JFrame.<init>(JFrame.java:158)
    at D3D.<init>(D3D.java:35)
    at player.<init>(player.java:1)
    at D3D.<init>(D3D.java:17)
    at player.<init>(player.java:1)
  

А вот и класс player:

 public class player extends D3D
{
  int playerX, playerY;
  boolean east, west, south, north;
  public void setPlayer()
  {
    playerX = 1; playerY = 1;
    east=true; west=false; north=false; south=false;
  }
}
  

А вот и класс D3D:

 public class D3D extends JFrame
{
  player player = new player();
  mapgeneration levelmap = new mapgeneration();
  boolean ONE, TWO, THREE, FOUR, FIVE;
  boolean ONEhighlight,TWOhighlight,THREEhighlight,FOURhighlight,FIVEhighlight;
  Timer timer = new Timer(250,new ActionListener() {
    public void actionPerformed(ActionEvent evt) {
      repaint();
    }
  });

  String tracer;

  Image Example = Toolkit.getDefaultToolkit().getImage("images/example.png");
  Image Startup = Toolkit.getDefaultToolkit().getImage("images/Startup.png");
  Image ButtonHighlight = Toolkit.getDefaultToolkit().getImage("images/ButtonHighlight.png");

  public D3D()
  {
    super();
    setSize(342,277);

      ...
    JPanel main = new JPanel()
    {
      public void paintComponent(final Graphics g)
      {
        super.paintComponent(g); 
        timer.start();
        g.drawImage(Startup,0,0,this);
        ...
      };
    };
    add(main);
  }
  public void init()
  {
    player.setPlayer();
    levelmap.populateGraph();
  }
  public static void main(String[] args)
  {
    D3D game = new D3D();
    game.setTitle("Dungens:3D");
    game.init();
    game.setVisible(true);
  }
}
  

Я просматривал это в течение нескольких часов и сузил список до того, что вы видите здесь. Честно говоря, это, вероятно, какая-то глупая маленькая мелочь, на которую я смотрю.

Спасибо, ребята.

Комментарии:

1. Я не вижу, в чем заключается ваша рекурсия, если только это не потому, что вы запускаете объект Timer в методе paintComponent (что более чем немного странно) и вызываете repaint () внутри этого же таймера! Я думаю, что вам нужно будет создать и опубликовать SSCCE , чтобы кто-нибудь мог решить это за вас.

2. Нет, таймер объявлен вне метода paintComp; он находится в классе. Может быть, я смогу получить ее, если кто-нибудь сможет сказать мне, что это значит: at D3D.<init>(D3D.java:35) at player.<init>(player.java:1 Означает ли это, что ошибка возникает в строке 35 D3d и строке 1 player?

3. Это не вызывает рекурсию, но вы все еще запускаете ее в paintComponent, и, честно говоря, вам просто не следует этого делать. Никакая программная логика не должна вызываться из этого метода.

Ответ №1:

Я вижу вашу проблему. Ваш класс Player расширяет ваш графический интерфейс D3D, вызывая своего рода сумасшедшие циклические ссылки. Это вызовет рекурсию, поскольку вы циклически продолжаете создавать проигрыватели и объекты D3D.

Чтобы доказать, что я прав, просто запустите эту очень простую версию вашего кода:

 public class D3D {
   Player player = new Player();

   public static void main(String[] args) {
      D3D game = new D3D();
   }
}

class Player extends D3D {

}
  

Итак, когда создается объект D3D, он создает объект Player, и поскольку он расширяет D3D, он создает другой объект Player, который, в свою очередь, поскольку это объект D3D, создает другой объект Player, и так далее, и тому подобное.

Но даже если это не вызвало рекурсию, Player никогда не следует расширять GUI, поскольку player не является gui; это совершенно разные логические конструкции.

Комментарии:

1. Подождите, что. Вам даже разрешено это делать? (т.е. нет ошибки компилятора?) Хороший улов xX

2. @Voo: C / C — не единственный язык, который позволяет вам выстрелить себе в ногу (хотя C / C заряжает пистолет и направляет его на вас).