Java空指针异常 - 不明白为什么

时间:2010-10-30 23:09:27

标签: java exception null nullpointerexception

MovieList.java中main方法的运行时错误。

我不确定我的程序设计从根本上说是非常好,但我想知道它崩溃的原因。提前谢谢。

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

6 个答案:

答案 0 :(得分:8)

程序在尝试将新Movie添加到myFavouriteMovies时崩溃,因为myFavouriteMoviesnull

虽然myFavouriteMovies已初始化为新的空ArrayList,但它会在null构造函数中设置为MovieList1

目前,myFavouriteMoviesstatic,因此每个MovieList1实例之间只共享此变量的一个副本。您可能希望从static声明中删除myFavouriteMovies修饰符。然后,每个MovieList1对象都有自己的myFavouriteMovies字段。但是,您将在MovieList1类中添加一个新方法,以允许您的main方法将影片添加到影片列表中,可能是这样的:

List.add(TempMovie);

此外,您还需要删除

this.myFavouriteMovies = null;

来自构造函数,因为已将其初始化为空ArrayList,您不希望将其重新设置为null

答案 1 :(得分:2)

在您的构造函数中设置

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

你已经在上面宣布了myFavouriteMovies之后。这可能会导致NullPointer

答案 2 :(得分:1)

当您调用MovieList1的构造函数时,将ArrayList MyFavouriteMovies设置为null。如果您在MyFavouriteMovies上调用方法,则会出现空指针异常(位于myFavouriteMovies.add(TempMovie);)。

this.myFavouriteMovies = null;应为this.myFavouriteMovies = new ArrayList(); private static ArrayList myFavouriteMovies = new ArrayList();应为private ArrayList myFavouriteMovies;

顺便说一句,我不会将myFavouriteMovies设为静态,因为它对于MovieList1的每个实例都不同。然后,您将在MovieList1中使用方法addMovie()。此外,如果NUM_OF_MOVIES是常量,正如大写名称所示,您应该将其声明为最终。

答案 3 :(得分:1)

所有上述答案都是现场的,但我怀疑你是否甚至需要MovieList1课程。基本上,你只是提供List的包装器。我不确定你是否有计划扩展电影列表的行为,但是你可以这样做:

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

其他一些说明......

您可能应该在电影列表类中使用addMovie(Movie movie)方法或类似方法,而不是直接在main方法中访问列表。

您应该program to the interface而不是将ArrayList声明为myFavoriteMovies的类型。

没有必要覆盖构造函数中的值,因为您在声明它们时已经实例化或初始化它们。

你可能会通过调用this.myFavoriteMovies来获得警告,因为它是静态的。应该通过ClassName.staticMethodOrVariable访问静态成员和方法。我只提到这一点,因为this暗示的内容与静态内容之间存在很大差异。 This指的是类型的当前引用,而static指的是持久的。此外,在声明不可变的静态成员时,请使用final修饰符,但在这种情况下,我认为它不需要是静态的,但绝对可以是最终的。

答案 4 :(得分:0)

理查德对问题的答案是正确的。但是有一个更好的解决方案。

当您声明变量时,您应该考虑是否要更改它。如果你没有把它标记为最终版。

所以:

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;

这意味着你需要摆脱大多数setXXX方法 - 如果你考虑一下,你永远不想在创建实例之后更改值。 numberOfMovies和index可能需要更改,因此它们不是最终的。最后(没有双关语!)你不需要将实例变量设置为0,null或false,默认情况下将它们设置为。

答案 5 :(得分:0)

我观察到你没有很好的编程逻辑。您还需要进一步了解Java运行时的流程和语言的行为。无论您是使用Java,C,C ++还是英语进行交流,逻辑流程都是您需要获得的技能。 (顺便说一句,英语,尽管有不一致的合成元素,但却是一种分析逻辑语言。)

首先,声明一个静态myFavouriteMovies并将其实例化为ArrayList。之后,将它等同于null。将变量等于null后,您尝试将其用作

myFavouriteMovies.add(TempMovie);

当然,你会得到一个空指针。

您需要熟悉编译器和运行时错误转储。 Java运行时错误肯定会指出您在尝试从空的非透支保护银行账户中提取资金时的声明号。

由“VB专家”编写的C#程序总是让我感到沮丧。我意识到这不是一种善意的回应,但我表达了一种非常冒昧的态度,说你很有可能是一位熟练的Visual Basic程序员。因此,我正在通过在开放式伤口(盐作为消毒剂)上撒盐来向所有熟练的Visual Basic程序员提供进一步的机会,您绝不应该将对象引用语言中的编程专业知识转移到面向对象的语言。就像希腊语或希伯来语这样的合成逻辑语言的专家演讲者难以适应像英语这样的分析逻辑语言一样,反之亦然。

其次,你将myFavouriteMovies声明为静态的原因是什么?你是否意识到静态变量的含义?

第三,你不应该在类实例引用“this”中引用静态变量。 myFavouriteMovies是Movie类中的静态变量。因此,您应该将其称为

Movie.myFavouriteMovies

而不是

this.myFavouriteMovies

Java允许您执行此类异常参考,但C#不会。 “this”应保留为“实例变量”。

最后,与其他“VB专家”相比,很有可能需要进一步了解实例变量与静态变量的关系。存在静态变量而无需实例化类。因此,它被所有类的实例“共享”;如果它是公共的或受保护的,则与该静态变量所暴露的任何流程元素共享。

通常,当您有静态列表时,get方法不应返回该静态变量的引用。您应该返回列表的子集。例如,您可以拥有每部电影的所有粉丝的静态列表。当您需要返回特定影片的粉丝列表时,您不会返回整个静态列表,而只返回该静态列表的子集。您需要了解何时可以使用静态变量并限制自己部署静态引用 - 这意味着,如果使其成为类实例,则不要声明变量static。

您可以使用静态变量来监视和限制Movie类未实例化超过,例如,五次或当前没有超过五个实例,通过每次实例化时递增静态计数并每次递减它被摧毁了。您可以使用静态变量来保存与数据库的连接池,其中每个连接都是连接的实例。

小琐事: 您是否知道可以使用静态块在Java中执行静态操作?如果有多个静态块,它们将按声明的顺序进行处理。像往常一样,在代码块内声明的任何变量在该块之外都不可见。

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

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

您应该尝试在静态代码块中实例化静态变量。如果您发现可以在实例构造函数中实例化静态变量,则很可能它不应该是静态的。

阅读:静态代码块的执行流程 - http://forums.sun.com/thread.jspa?threadID=5418566。 2017-06-30:这个太阳论坛主题已存档 https://community.oracle.com/message/5266256#5266256 这需要oracle acct注册才能访问。