2010-10-30 196 views
2

MovieList.java中main方法的运行时错误。Java空指针异常 - 不明白为什么

我不确定我的程序设计是否从根本上说非常好,但是我想知道它为什么会崩溃。提前致谢。

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

虽然它是一个空*指针*异常,我删除了指针标签。在Java中讨论指针是没有意义的。另外,如果这是家庭作业,请添加“家庭作业”标签。 – Synesso 2010-10-30 23:20:14

回答

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是不变的,如大写字母名称所暗示的那样,您应该声明它是最终的。

8

当程序试图将新的Movie添加到myFavouriteMovies时,程序崩溃,因为myFavouriteMoviesnull

虽然myFavouriteMovies被初始化到一个新的空ArrayList,它然后在MovieList1构造函数设置为null

目前,myFavouriteMoviesstatic,所以在每个MovieList1实例之间只共享此变量的一个副本。您可能想要从myFavouriteMovies声明中删除static修饰符。然后每个MovieList1对象都会有自己的myFavouriteMovies字段。但是你会再到一个新的方法添加到MovieList1类,让您的main方法添加到动画到电影列表,或许是这样的:

List.add(TempMovie); 

你也需要删除

this.myFavouriteMovies = null; 

从构造函数,因为已初始化为空ArrayList,您不想将其设置回null

2

在构造函数中要设置

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

您已经声明上述myFavouriteMovies后。这可能会导致一个空指针

+1

是的。 @James是myFavouriteMovies静态的,还是一个实例变量?选择一个并仅实例化一次。 – Synesso 2010-10-30 23:17:43

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)方法或类似的方法,而不是直接在主方法中访问列表。

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

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

您可能会通过调用this.myFavoriteMovies来获得警告,因为它是静态的。静态成员和方法应该由ClassName.staticMethodOrVariable访问。我只提到这一点,因为this意味着什么和静态是什么有很大的区别。 This指的是该类型的当前引用,而静态意味着是持久的。另外,在声明不可变静态成员时,使用final修饰符,但在这种情况下,我不认为它需要是静态的,但可以肯定是最终的。

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方法 - 如果你仔细想想,你永远不希望你反正创建一个实例后更改值。数字电影和索引大概需要改变,所以它们不是最终的。最后(没有双关语!)你不需要设置实例变量为0,null或者false,它们默认设置为那个。

0

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

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

myFavouriteMovies.add(TempMovie); 

当然,您将得到一个空指针。

您需要熟悉编译器和运行时错误转储。 Java运行时错误肯定会指出它的语句编号,它遇到了您尝试从空的非透支保护的银行账户中提取资金的情况。

“VB专家”编写的C#程序总是让我很沮丧。我意识到这不是一种善意的回应,但我认为你非常有可能是一名熟练的Visual Basic程序员,所以我非常冒昧地表态。因此,我正在通过向开放性伤口(盐作为消毒剂)投掷盐来让所有精通Visual Basic程序员获得更多机会,您绝对不应该将您的编程专业知识以对象引用语言转换为面向对象语言。正如希腊语或希伯来语等合成逻辑语言的专家很难适应像英语这样的分析逻辑语言,反之亦然。

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

第三,你不应该引用类实例引用“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注册来访问。