0

I'm making a guess the movie game in which i take a list of movies from a text file. I have two classes for it Game for getting a random movie and Main for the rest of the game. Now i thought of adding a choice for hollywood or bollywood movies by changing the text files in Game. I take 'h' or 'b' respectively as inputs. I call the constructor of Game with parameters to choose file accordingly but it doesn't work and ALWAYS the file is null and showing NullPointerException.

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

EDIT: I am new to OOPs so please bear with me. I just saw during debugging that the debugger first goes to the class fields and THEN to the constructor, I was actually trying to use file(which is inside the constructor) for the initialization of other fields because of which its value was null and was showing NullPointerException.

Now my question really remains how to use file and noOfMovies to initialize other fields in 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];


    }




TheGeek
  • 23
  • 8
  • add an else block with a message after the 2 other `if` - so you know what is being passed: `} else { System.out.println("unrecognized genre: " + genre); }` or throw an Exception: `} else { throw new IllegalArgumentException("invalid genre: " + genre); }` {{probably the error is how you are determining that file is null, we can't see that part}} – user85421 May 06 '19 at 17:21
  • Please use a debugger to find out what is actually happening. A common problem may be that the `src` directory is not available when you actually run the code, or the path is misspelled somehow. Print the path before opening the file and check if the file exists using shell. –  May 06 '19 at 17:22
  • @CarlosHeuberger i know it'll look silly but i feel that it never goes into the constructor and setMovieList is never called as i used debugger and it NEVER stops inside the constuctor or on the setMovieList. It ALWAYS skips it and uses the initial values instead. – TheGeek May 06 '19 at 17:51
  • then or the first posted part is not being executed, or there is another `Game` class (another package, or actual version not compiled). Stop the debugger at the statement with `new Game` and see where it is jumping into {{just confirm that your constructor is not declared like `public void Game(char genre)` - a simple method, not a constructor} – user85421 May 06 '19 at 17:54
  • The code you posted here seems good... it works as expected, it goes in the constructor and call properly the setMovieList... are you sure you are executing exactly this code? – D Gub May 06 '19 at 17:59
  • @DGub It compiles without errors but the `file` and `noOfMovies` values are still `null`and `0`THAT is the problem because afterwards i am not able to use them – TheGeek May 06 '19 at 18:37
  • @CarlosHeuberger Nope. Just confirmed it. It is not a typo – TheGeek May 06 '19 at 18:40
  • well I wrote a bit more... but I think we heve enough guesses here - we need a [mcve] (e.g. missing the random field which must be one since initialized before the constructor is called) – user85421 May 06 '19 at 20:54
  • a minimal example code would be above code and `public static void main(String[] args) { Game game = new Game('b'); System.out.println(game.file); }` – user85421 May 06 '19 at 21:05
  • @CarlosHeuberger @DGub I am new to oops so please bear with me . I just saw during debugging that the debugger first goes to the fields and then to the constructor, I was actually calling `file` in the field initialization because of which its value was setting to null and everything was collapsing. – TheGeek May 07 '19 at 03:34
  • @CarlosHeuberger @DGub Please check out the rest of the code I added. Now my question is how to use `file` and `noOfMovies` to initialize other fields in `Game`. – TheGeek May 07 '19 at 03:40

2 Answers2

1

I'm not sure.. maybe you want to get a result like this:

GAME CLASS

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;
 }

}

MAIN CLASS

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);
 }
}

Note i've used List data structure in place of array but it is obviously up to you... let me know if this may look like what you are trying to do... some other improvements can certainly be made but should work.

Also it assumes you have a txt file with movie titles separated by semicolon...otherwise you have to adjust the split method in the getList one..

Furthermore this way you no longer need the noOfMovies field cause it takes automatically the list size.

Hope it helps...

D Gub
  • 26
  • 5
0

The problem is that the fields are initialised before the constructor is called.

There are a number of things you should do:

  1. Don't call getters and setters from a constructor. See this question: Should I use getters and setters in constructors?

  2. If you are doing complex initialisation logic, do it all in the constructor. Only initialise fields directly with very basic values (not ones that depend other fields). In your case, it will be easier just to do everything in the constructor. This avoids the problem that you change your code to modify a value in the constructor and some field initialisation stops working.

rghome
  • 8,529
  • 8
  • 43
  • 62
  • Did you mean to say that I should initialized `scan` , `random` and `movieArray` too in the constructor? I just tried to do that but now the `scan` initialization complains that `Unhandled exception:Java.io.FileNotFoundException` If you want i can put the code or image of it. – TheGeek May 07 '19 at 13:21
  • It actually works if I attach a try-catch block to it, but i have do it in `Game` and in every line of `Main` that calls the `Game` object .Is this the only way to do it? – TheGeek May 07 '19 at 13:37