【问题标题】:How to use constructor to set other fields that are not inside constructor如何使用构造函数设置不在构造函数内的其他字段
【发布时间】:2019-05-06 17:16:17
【问题描述】:

我正在猜测我从文本文件中获取电影列表的电影游戏。我有两个课程 Game 用于获取随机电影,Main 用于游戏的其余部分。现在我想通过更改Game 中的文本文件来添加好莱坞或宝莱坞电影的选择。我分别将“h”或“b”作为输入。我用参数调用Game 的构造函数以相应地选择文件,但它不起作用,并且文件总是null 并显示NullPointerException

This image showing what happens during debugging. It skips the setMovieList and constructor and comes to the next line

编辑:我是 OOP 的新手,所以请多多包涵。我刚刚在调试过程中看到调试器首先进入类字段,然后进入构造函数,我实际上试图使用file(在构造函数内部)来初始化其他字段,因为它的值是@987654330 @ 并显示 NullPointerException

现在我的问题仍然是如何使用filenoOfMovies 来初始化Game 中的其他字段。

              //showing the setter method that i tried
//Main class
/*only showing the part having Game class*/

//making an object of Game class to get a random movie from the file
    System.out.println("Enter 'h' for hollywood and 'b' for bollywood ");
    Scanner input = new Scanner(System.in);
    char genre = input.next().charAt(0);
    Game newGame = new Game(genre);


//Game class
public class Game
{

    public Game(char genre)
    {
        setMovieList(genre);
    }
    File file;
    int noOfMovies;

    public void setMovieList(char genre)
    {
        if(genre == 'h')
        {
            this.file = new File("C:\\Users\\Rashim\\Desktop\\java\\GuessTheMovie\\src\\hollywoodMovies.txt");
            this.noOfMovies = 30;
        }
        else if(genre == 'b')
        {
            this.file = new File("C:\\Users\\Rashim\\Desktop\\java\\GuessTheMovie\\src\\bollywoodMovies.txt");
            this.noOfMovies = 20;
        }

    // EDIT ------> I want to initialize the below fields <-------

        private Scanner scan = new Scanner(this.file);

        private int lineCount = 0;
        int random = (int)(Math.random()*noOfMovies)+1;

        //array for storing the movie titles
        private String[] movieArray = new String[noOfMovies];


    }




【问题讨论】:

  • 在另外两个 if 之后添加一个带有消息的 else 块 - 所以你知道正在传递什么:} else { System.out.println("unrecognized genre: " + genre); } 或抛出异常:} else { throw new IllegalArgumentException("invalid genre: " + genre); } {{可能错误是你如何正在确定该文件为空,我们看不到该部分}}
  • 请使用调试器找出实际发生的情况。一个常见的问题可能是当您实际运行代码时,src 目录不可用,或者路径拼写错误。打开文件前打印路径,并使用shell检查文件是否存在。
  • @CarlosHeuberger 我知道它看起来很傻,但我觉得它永远不会进入构造函数,并且 setMovieList 永远不会因为我使用调试器而被调用,它永远不会在构造函数内或 setMovieList 上停止。它总是跳过它并使用初始值。
  • then 或者第一个发布的部分没有被执行,或者有另一个Game 类(另一个包,或者没有编译的实际版本)。在带有new Game 的语句处停止调试器并查看它跳转到的位置{{只需确认您的构造函数没有像public void Game(char genre) 那样声明 - 一个简单的方法,而不是构造函数}
  • 您在此处发布的代码看起来不错...它按预期工作,它进入构造函数并正确调用 setMovieList...您确定您正在执行此代码吗?

标签: java oop constructor


【解决方案1】:

我不确定..也许你想得到这样的结果:

游戏类

import java.io.*;
import java.util.ArrayList;
import java.util.List;

public class Game {

    private File file = null;
    //private int noOfMovies = 0;
    private List<String> movies= null;
    FileInputStream read = null;

public Game(char genre) {
     movies = getMovieList();
     System.out.println(movies);
}

public void setMovieList(char genre) {
    if (genre == 'h') {
        this.file = new File("C:\\Users\\Rashim\\Desktop\\java\\GuessTheMovie\\src\\hollywoodMovies.txt");
      //  this.noOfMovies = 30;
    } else if (genre == 'b') {
        this.file = new File("C:\\Users\\Rashim\\Desktop\\java\\GuessTheMovie\\src\\bollywoodMovies.txt");
      //  this.noOfMovies = 20;
    }

}

public List<String> getList() {
    List<String> movieList = new ArrayList<>();
    String[] values = null;
    try (BufferedReader br = new BufferedReader(new FileReader(file))) {
        String line;
        while ((line = br.readLine()) != null) {
            values = line.split(";");
            movieList.add(values[0]);
        }
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

    return movieList;
}

public String getMovie(){
    System.out.println(movies.size());
    int min = 1;
    int max = movies.size();
    int random = min + (int) (Math.random() * (max - min));

    System.out.println(random);
    String title = movies.get(random);
    return title;
 }

}

主类

import java.util.Scanner;

public class Main {

  public static void main(String[] args) {

    System.out.println("Enter 'h' for hollywood and 'b' for bollywood ");
    Scanner input = new Scanner(System.in);
    char genre = input.next().charAt(0);
    Game newGame = new Game(genre);

    String randomMovie = newGame.getMovie();
    System.out.println(randomMovie);
 }
}

请注意,我使用 List 数据结构代替数组,但这显然取决于您...如果这看起来像您正在尝试做的事情,请告诉我...当然可以进行一些其他改进,但是应该可以。

还假设您有一个 txt 文件,其中电影标题用分号分隔...否则您必须调整 getList one 中的拆分方法..

此外,您不再需要 noOfMovies 字段,因为它会自动获取列表大小。

希望对你有帮助...

【讨论】:

    【解决方案2】:

    问题是字段在构造函数被调用之前被初始化。

    你应该做很多事情:

    1. 不要从构造函数中调用 getter 和 setter。看到这个问题:Should I use getters and setters in constructors?

    2. 如果您正在执行复杂的初始化逻辑,请在构造函数中执行所有操作。仅使用非常基本的值(而不是依赖于其他字段的值)直接初始化字段。在你的情况下,在构造函数中做所有事情会更容易。这避免了您更改代码以修改构造函数中的值并且某些字段初始化停止工作的问题。

    【讨论】:

    • 你的意思是说我应该在构造函数中初始化scanrandommovieArray?我只是尝试这样做,但现在scan 初始化抱怨Unhandled exception:Java.io.FileNotFoundException 如果你愿意,我可以放它的代码或图像。
    • 如果我附加一个 try-catch 块,它实际上可以工作,但是我在Game 和调用Game 对象的Main 的每一行中都这样做了。这是唯一的办法吗?
    猜你喜欢
    • 1970-01-01
    • 2017-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-17
    • 1970-01-01
    • 2018-02-20
    • 2013-10-29
    相关资源
    最近更新 更多