2010-10-30 21 views
2

Erreur d'exécution de la méthode principale dans MovieList.java.Java null pointer exceptions - ne comprend pas pourquoi

Je ne suis pas sûr que la conception de mon programme soit fondamentalement très bonne, mais j'aimerais savoir pourquoi il se bloque. Merci d'avance.

package javaPractical.week3; 

import javax.swing.*; 

public class Movie { 
    //private attributes 
    private String title; 
    private String movieURL; 
    private String year; 
    private String genre; 
    private String actor; 

    // constructor 
    Movie(String t, String u, String y, String g, String a) { 
     this.title = t; 
     this.movieURL = u; 
     this.year = y; 
     this.genre = g; 
     this.actor = a; 

    } 
    //getters and setters 
    public void setTitle(String t) { 
     this.title = t; 
    } 

    public String getTitle() { 
     return this.title; 
    } 

    public void set_url(String a) { 
     this.movieURL = a; 
    } 

    public String get_url() { 
     return this.movieURL; 
    } 

    public void setYear(String y) { 
     this.year = y; 
    } 

    public String getYear() { 
     return this.year; 
    } 

    public void setGenre(String g) { 
     this.genre = g; 
    } 

    public String getGenre() { 
     return this.genre; 
    } 

    public void setActor(String a) { 
     this.actor = a; 
    } 

    public String getActor() { 
     return this.actor; 
    } 


    //output movie details 
    public String toString() { 
     return ("Title: " + this.title + "\nURL: " + this.movieURL + "\nYear: " 
      + this.year + "\nGenre: " + this.genre + "\nActor: " 
      + this.actor); 
    } 

    public static void main(String[] args) { 
     //testing Movie class 
     Movie Movie1 = new Movie("Spiderman", "www.", "2002", "Action", 
      "Tobey M"); 

     JOptionPane.showMessageDialog(null, Movie1.toString()); 
     //testing MovieList class 
    } 
} 

package javaPractical.week3; 

import javax.swing.*; 

import java.util.ArrayList; 

public class MovieList1 { 

    private static ArrayList myFavouriteMovies = new ArrayList(); 
    private static int NUM_OF_MOVIES = 10; 
    private int numberOfMovies = 0; 
    private int index = 0; 

    public MovieList1() { 
     this.myFavouriteMovies = null; 
     this.numberOfMovies = 0; 
     this.index = 0; 
    } 

    public int getNumberOfMovies() { 
     return this.myFavouriteMovies.size(); 
    } 

    public boolean isEmpty() { 
     if (this.myFavouriteMovies.isEmpty()) { 
      return true; 

     } else 
     return false; 

    } 

    public static void main(String[] args) { 
     MovieList1 List = new MovieList1(); 
     String titleADD; 
     String movieURLADD; 
     String yearADD; 
     String genreADD; 
     String actorADD; 

     titleADD = JOptionPane.showInputDialog(null, "Enter title:"); 
     movieURLADD = JOptionPane.showInputDialog(null, "Enter URL:"); 
     yearADD = JOptionPane.showInputDialog(null, "Enter year:"); 
     genreADD = JOptionPane.showInputDialog(null, "Enter genre:"); 
     actorADD = JOptionPane.showInputDialog(null, "Enter actor:"); 

     Movie TempMovie = new Movie(titleADD, movieURLADD, yearADD, genreADD, 
      actorADD); 

     myFavouriteMovies.add(TempMovie); 
    } 
} 
+3

Bien qu'il s'agisse d'une exception null * pointer *, j'ai supprimé la balise pointeur. Cela n'a pas de sens de parler de pointeurs en Java. Aussi, s'il vous plaît ajouter la balise 'devoirs' si c'est les devoirs. – Synesso

Répondre

1

Lorsque vous appelez le constructeur pour MovieList1, vous définissez les ArrayList MyFavouriteMovies à null. Si vous appelez des méthodes sur MyFavouriteMovies, il existe une exception de pointeur null (à myFavouriteMovies.add(TempMovie);).

this.myFavouriteMovies = null; devrait être this.myFavouriteMovies = new ArrayList(); et private static ArrayList myFavouriteMovies = new ArrayList(); devrait être private ArrayList myFavouriteMovies;

D'ailleurs, je ne ferais pas myFavouriteMovies statique, car il est différent pour chaque instance de MovieList1. Vous auriez alors une méthode addMovie() dans MovieList1. De même, si NUM_OF_MOVIES est constant, comme le suggère le nom en majuscule, vous devez le déclarer final.

8

Le programme se bloque lorsqu'il tente d'ajouter le nouveau Movie à myFavouriteMovies, car myFavouriteMovies est null.

Bien que myFavouriteMovies est initialisée à un nouveau vide ArrayList, il est ensuite mis à null dans le constructeur MovieList1.

Pour le moment, myFavouriteMovies est static, donc il n'y a qu'une seule copie de cette variable partagée entre chaque instance MovieList1. Vous voulez probablement supprimer le modificateur static de la déclaration myFavouriteMovies. Ensuite, chaque objet MovieList1 aura son propre champ myFavouriteMovies. Cependant, vous serez alors d'ajouter une nouvelle méthode à la classe MovieList1 pour permettre à votre méthode main pour ajouter le film à la liste de film, peut-être comme ceci:

List.add(TempMovie); 

vous aurez également besoin d'enlever

this.myFavouriteMovies = null; 

du constructeur, car l'ayant initialisé à ArrayList vide, vous ne voulez pas le remettre à null.

2

Au sein de votre constructeur vous définissez

public MovieList1() { 
    this.myFavouriteMovies = null; 
    this.numberOfMovies = 0; 
    this.index = 0; 
} 

après avoir déjà déclaré myFavouriteMovies ci-dessus. Cela peut entraîner un NullPointer

+1

Oui. @James Est-ce que myFavouriteMovies est statique ou une variable d'instance? Choisissez-en un et instanciez-le une seule fois. – Synesso

1

Toutes les réponses ci-dessus sont sur place, mais je ne sais pas si vous avez besoin de la classe MovieList1. Essentiellement, vous fournissez simplement un wrapper autour de List. Je ne sais pas si vous prévoyez d'étendre les comportements de la liste des films, mais comme il est, vous pouvez simplement faire:

List<Movie> movies = new ArrayList<Movie>(); 
String titleADD = JOptionPane.showInputDialog(null, "Enter title:"); 
String movieURLADD = JOptionPane.showInputDialog(null, "Enter URL:"); 
String yearADD = JOptionPane.showInputDialog(null, "Enter year:"); 
String genreADD = JOptionPane.showInputDialog(null, "Enter genre:"); 
String actorADD = JOptionPane.showInputDialog(null, "Enter actor:"); 

Movie TempMovie = new Movie(titleADD, movieURLADD, yearADD, genreADD, actorADD); 
movies.add(TempMovie); 

Quelques autres notes ...

Vous devriez probablement avoir une méthode addMovie(Movie movie) ou quelque chose de similaire dans la classe de liste de films au lieu d'accéder à la liste directement dans votre méthode principale.

Vous devez program to the interface au lieu de déclarer un ArrayList comme type de myFavoriteMovies.

Il n'est pas nécessaire d'écraser les valeurs dans le constructeur car vous les avez déjà instanciées ou initialisées lorsque vous les déclarez.

Vous recevez probablement un avertissement en appelant this.myFavoriteMovies car il est statique. Les membres statiques et les méthodes doivent être accessibles par ClassName.staticMethodOrVariable. Je le mentionne seulement parce qu'il y a une grande différence entre ce que this implique et ce qu'est statique. This fait référence à la référence actuelle du type, alors que statique est destiné à être persistant. En outre, lors de la déclaration de membres statiques non modifiables, utilisez le modificateur final, mais dans ce cas, je ne pense pas que ce soit statique, mais définitivement définitif.

0

Richard a la bonne réponse à ce problème. Il y a une meilleure solution cependant.

Lorsque vous déclarez une variable, vous devez penser à la modifier si vous le souhaitez. Si vous ne le marquez pas comme final.

Alors:

private final String title; 
private final String movieURL; 
private final String year; 
private final String genre; 
private final String actor; 

private static final int NUM_OF_MOVIES = 10; 
private final List myFavouriteMovies = new ArrayList(); 
private int numberOfMovies; 
private int index; 

Cela signifie que vous devez vous débarrasser de la plupart des méthodes de setXXX - si vous pensez à ce que vous ne voulez modifier les valeurs après avoir créé une instance de toute façon. Le numberOfMovies et l'index doivent probablement changer, ils ne sont donc pas définitifs. Enfin (sans jeu de mots!) Vous n'avez pas besoin de mettre les variables d'instance à 0, null ou false, elles sont définies par défaut.

0

Je remarque que vous ne maîtrisez pas la logique de programmation. Vous devez également comprendre le flux de Java Runtime et le comportement de la langue. Pourtant, le flux logique est une compétence que vous devez acquérir, peu importe si vous communiquez en Java, C, C++ ou en anglais. (BTW, la langue anglaise, en dépit d'éléments synthétiques inconsistants, est un langage analytiquement logique.)

D'abord, vous déclarez un myFavouriteMovies statique et l'instanciez dans une ArrayList. Après cela, vous l'assimilez à null. Après avoir égalisé la variable à null, vous essayez de l'utiliser comme

myFavouriteMovies.add(TempMovie); 

Bien sûr, vous obtiendrez un pointeur null.

Vous devez vous familiariser avec le compilateur et les vidages d'erreurs d'exécution. L'erreur d'exécution de Java aurait certainement indiqué le numéro de déclaration où il a rencontré votre tentative de retirer de l'argent d'un compte bancaire vide non protégé.

Les programmes en C# écrits par des «experts VB» me frustrent toujours. Je me rends compte que ce n'est pas une réponse aimable, mais je projette une attitude très présomptueuse en disant que vous êtes hautement probable un programmeur Visual Basic compétent. Par conséquent, je profite de l'occasion pour tous les programmeurs Visual Basic compétents en jetant du sel sur une plaie ouverte (le sel étant un désinfectant), que vous ne devez JAMAIS transférer votre expertise de programmation dans un langage de référence aux langages orientés objet. Tout comme il est difficile pour un expert d'un langage synthétique comme le grec ou l'hébreu de s'adapter à une langue analytiquement logique comme l'anglais, et inversement.

Deuxièmement, quelle est la raison pour laquelle vous déclarez myFavouriteMovies statique? Réalisez-vous les implications d'une variable statique? Troisièmement, vous ne devez pas faire référence à une variable statique par la référence d'instance de classe "this". myFavouriteMovies est une variable statique dans la classe Movie. Par conséquent, vous devez vous référer comme

Movie.myFavouriteMovies 

et non comme

this.myFavouriteMovies 

Java vous permet d'effectuer une telle référence, mais aberrants C# ne serait pas. "this" devrait être réservé aux "variables d'instance". Finalement, il y a une grande probabilité, comparé à d'autres "experts VB", que vous ayez besoin de mieux comprendre quelles sont les variables d'instance par rapport aux variables statiques. Une variable statique existe sans avoir besoin d'une classe à instancier. Par conséquent, il est "partagé" par toutes les instances de la classe; et s'il est public ou protégé, il est partagé avec tous les éléments de processus auxquels cette variable statique est exposée.

Normalement, lorsque vous avez une liste statique, votre méthode get ne doit pas renvoyer la référence de cette variable statique. Vous devriez retourner un sous-ensemble de la liste. Par exemple, vous pouvez avoir une liste statique de tous les fans de chaque film. Lorsque vous devez renvoyer une liste de la liste des fans d'un film particulier, vous ne renvoyez pas toute la liste statique, mais uniquement un sous-ensemble de cette liste statique. Vous devez comprendre quand des variables statiques peuvent être utilisées et vous empêcher de déployer des références statiques - ce qui signifie, NE déclarez PAS de variable statique si cela fait fonctionner une instance de classe. Vous pouvez utiliser une variable statique pour surveiller et restreindre qu'une classe Movie n'est pas instanciée plus de, disons, cinq fois ou qu'il n'y a pas actuellement plus de cinq instances, en incrémentant un nombre statique chaque fois qu'elle est instanciée et décrémentée chaque fois qu'il est détruit. Vous pouvez utiliser une variable statique pour contenir un pool de connexions à la base de données, où chaque connexion est une instance d'une connexion. Savez-vous que vous pouvez effectuer une manipulation statique en Java en utilisant un bloc statique? S'il y a plus d'un bloc statique, ils seront traités dans l'ordre dans lequel ils ont été déclarés. Comme d'habitude, toute variable déclarée à l'intérieur d'un bloc de code n'est pas visible en dehors de ce bloc.

class Hello{ 
    static { 
    // perform static manipulation here 
    } 

    public void setAnInstanceValue(int a){ 
    ... 
    } 
    static { 
    // another static block of code here 
    } 
    ..... 
} 

Vous devriez essayer d'instancier vos variables statiques dans un bloc de code statique. Si vous trouvez que vous pouvez instancier une variable statique dans un constructeur d'instance, il est fort probable que cela ne soit pas statique. Lisez ceci: Flux d'exécution pour le bloc de code statique - http://forums.sun.com/thread.jspa?threadID=5418566. 2017-06-30: ce sujet de forum de soleil a été archivé à https://community.oracle.com/message/5266256#5266256 qui exige un enregistrement d'acct d'oracle pour accéder.