Получить строковый метод, возвращающий null, когда word определенно не равен null

#java #string #null

#java #строка #null

Вопрос:

Я пишу игру hangman, и по какой-то причине мой getW() метод возвращает значение null, когда он должен возвращать строку, которая определенно не равна null. Я тщательно добавил System.out.println s, чтобы убедиться, что он word остается неизменным. Кажется, что везде одно и то же, но в getW() методе, вот почему getW() возвращается null.

Это мой код:

Hangman.java:

 import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;

public class Hangman extends JPanel{
    private String word;

    public void setupLayout(JFrame window){
        window.setLayout(new GridBagLayout());
        GridBagConstraints c = new GridBagConstraints();

        HangmanArea panel1 = new HangmanArea();
        panel1.setBackground(Color.blue);
        c.fill = GridBagConstraints.BOTH;
        c.weightx = 1.0;
        c.weighty = 1.0;
        c.gridx = 0;
        c.gridy = 0;
        window.add(panel1, c);

        GuessedLetters panel2 = new GuessedLetters();
        panel2.setBackground(Color.green);
        c.fill = GridBagConstraints.BOTH;
        c.gridx = 1;
        c.gridy = 0;
        window.add(panel2, c);

        Letters panel3 = new Letters();
        panel3.setBackground(Color.black);
        c.fill = GridBagConstraints.BOTH;
        c.gridx = 0;
        c.gridy = 1;
        c.gridwidth = 2;
        window.add(panel3, c);
        System.out.println("Before repaint: "  word);
        panel1.callRepaint();
        panel2.callRepaint();
        panel3.callRepaint();
        System.out.println("After repaint: "   word);
    }

    public void startWindow(){
        JFrame window = new JFrame();
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        int screenHeight = (int) screenSize.getHeight();
        int windowHeight = (int) ((screenHeight / 4) * 3);
        window.setSize(windowHeight, windowHeight);
        window.setLocationRelativeTo(null);
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setupLayout(window);
        window.setVisible(true);
    }

    public void startGame(){
        Prep prepare = new Prep();
        word = prepare.findWord(true);
        System.out.println("Word found: "   word);
        startWindow();
        System.out.println("Word is unchanged: "   word);
    }

    public static void main(String[] args){
        Hangman start = new Hangman();
        start.startGame();
    }
    public String getW(){
        System.out.println("getW()'s word: "   word);    //At this point, word is null
        return word;
    }
}
  

Letters.java:

 import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;

public class Letters extends JPanel {
    private String word = "aaa";
    public void callRepaint(){
        Hangman object = new Hangman();
        word = object.getW();
        System.out.println("Word for Letters: "   word);
        repaint();
    }
    public void paintComponent(Graphics g){
        super.paintComponent(g);
        g.setColor(Color.white);
        g.drawString("letters", 50, 50);
    }
}
  

Извините, если это кажется слишком большим количеством кода, но Hangman.java и Letters.java это два важных класса. Prep.java findWord() метод просто берет случайное слово из списка слов и возвращает его. Я не думаю, что это необходимо публиковать, но я могу. GuessedLetters.java и HangmanArea.java полностью пусты, за исключением методов callRepaint() и paintCompnent(Graphics g) . Я могу опубликовать их, если вам нужно, но я не думаю, что они очень важны.

Вывод может выглядеть следующим образом:

 Word found: night
Before repaint: night
getW()'s word: null
Word for Letters: null
After repaint: night
Word is unchanged: night
  

Я понятия не имею, что является причиной этого.

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

1. Почему callRepaint создается новый экземпляр Hangman ? очевидно, что ему не будет присвоено правильное word значение, поскольку оно не совпадает с вашим основным объектом

Ответ №1:

Проблема в том, что вы не передаете объект, для которого word переменная инициализирована (значением «night» в опубликованном вами примере вывода), в callRepaint метод, вместо этого создавая новый экземпляр внутри этого метода (который не подключен к вашему «основному» объекту). Вместо этого вы должны либо передать объект в качестве параметра, например:

 public void callRepaint(Hangman object){
        word = object.getW();
        System.out.println("Word for Letters: "   word);
        repaint();
}
  

и вызовите его следующим образом внутри вашего Hangman класса:

 panel1.callRepaint(this);
panel2.callRepaint(this);
panel3.callRepaint(this);
  

или, возможно, просто передать String , например:

 public void callRepaint(String word){
        System.out.println("Word for Letters: "   word);
        repaint();
}
  

и назовите это так:

 panel1.callRepaint(getW());
panel2.callRepaint(getW());
panel3.callRepaint(getW());
  

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

1. Спасибо. Это раздражает меня уже некоторое время.

Ответ №2:

В callRepaint вы создаете новый объект Hangman, word член которого никогда не инициализируется.

Либо вы объявляете свою переменную word статической, что означает, что каждый экземпляр Hangman будет совместно использовать эту переменную (это больше не член класса, и это плохой стиль кодирования), либо вы добавляете исходный экземпляр Hangman в качестве параметра при создании экземпляра класса Letters или во время вызова callRepaint. Или вы устанавливаете слово-член Hangman в качестве параметра при создании экземпляра Letters.