I am getting an error when I run my program that says:

Exception in thread "main" java.lang.NullPointerException
    at defaultpackage.GradeBook.setName(GradeBook.java:25)
    at defaultpackage.GradeBookDemo.readFromFile(GradeBookDemo.java:52)
    at defaultpackage.GradeBookDemo.main(GradeBookDemo.java:23)

I've looked through my program and cannot figure out what is actually wrong. The first class is GradeBook and the second is GradeBookDemo. I have to use GradeBookDemo to import a file of students and test scores and return each specific student's name, average test score, and a letter grade based on the average. I also am not sure how to output each student's name with their average test score and letter grade. If I could get some help on how to fix this error and how to output the above that would be great. Thank you!

public class GradeBook 
{ 

    String[] names; //array to hold student's names

    char[] letterGrades; //array to hold student's letter grades

    double[] scores1 = new double[4]; //five arrays to hold each students' scores
    double[] scores2 = new double[4]; 
    double[] scores3 = new double[4]; 
    double[] scores4 = new double[4]; 
    double[] scores5 = new double[4]; 

    public void setName(int studentNumber, String name) 
    { 
        names[studentNumber-1]=name; 
    } 

    public void setScores(int studentNumber, double[] scores) 
    { 
        if(studentNumber==1) 
            scores1=copyArray(scores); 
    } 

    public double[] copyArray(double[] from) 
    { 

        double[] to = new double[from.length]; 
        for (int i = 0; i <from.length; i++) 
            to[i]=from[i]; 
        return to; 
    } 
    public String getName(int studentNumber)  
    { 
        return names[studentNumber-1]; 
    } 

    public String getAverage(int i)  
    { 
        double total; 
        double average = 0; 
        total = 0; 
        for (int row = 0; row < 4; row++) 
            total += scores1 [row]; 
        average = total/4; 
        System.out.println("Average: " + average); 

        for (int row = 0; row < 4; row++) 
            total += scores1 [row]; 
        average = total/4; 
        System.out.println("Average: " + average); 

        for (int row = 0; row < 4; row++) 
            total += scores2 [row]; 
        average = total/4; 
        System.out.println("Average: " + average); 

        for (int row = 0; row < 4; row++) 
            total += scores3 [row]; 
        average = total/4; 
        System.out.println("Average: " + average); 

        for (int row = 0; row < 4; row++) 
            total += scores4 [row]; 
        average = total/4; 
        System.out.println("Average: " + average); 

        for (int row = 0; row < 4; row++) 
            total += scores5 [row]; 
        average = total/4; 
        System.out.println("Average: " + average); 

        return null; 
    } 

    public String getLetterGrade(int i)  
    { 
        double grade; 
        double average = 0; 
        if (average > 90) 
            grade = 'A'; 
        else if (average > 80) 
            grade = 'B'; 
        else if (average > 70) 
            grade = 'C'; 
        else if (average > 60) 
            grade = 'D'; 
        else grade = 'F'; 

        return null; 
    } 
} 



import 
java.util.Scanner; 
import 
java.io.*; 
/** 
 * GradeBookDemo program 
 * This program tests the GradeBook class by 
 * using the data stored in the StudentInfo.txt 
 * file. 
 */ 
public 
class GradeBookDemo 
{ 
    public static void main(String[] args) 
    throws IOException 
    { 
        // Create a GradeBook object. 
        GradeBook gb =  
            new GradeBook(); 
        // Read the data from the file and put the data into grade book gb 
        readFromFile(gb); 
        // Display the student data. 
        for (int i = 1; i <= 5; i++) 
        { 
            System. 
            out.println("Name : " + gb.getName(i) + 
                    "\tAverage score: " +  
                    gb.getAverage(i) + 
                    "\tGrade: " +  
                    gb.getLetterGrade(i)); 
        } 
    } 

    /** 
     * readFromFile method 
     */ 
    public static void readFromFile(GradeBook gb) 
    throws IOException 
    { 
        int i = 0; 
        int ROWS = 4; 
        double [] scores = new double [ROWS]; 

        File file = new File ("StudentInfo.txt"); 
        Scanner inputFile = new Scanner(file); 
        for(int student = 1; student <= 5; student++) 
        { 
            String name = inputFile.nextLine(); 
            gb.setName(student, name); 
            for(int test = 0; test<4; test++)
            { 
                scores[test]=inputFile.nextDouble(); 
            } 
            gb.setScores(student, scores); 
        } 
        inputFile.close();
    } 
}

Edited 3 Years Ago by codys21

I know it doesn't address the problem you are having (directly, anyway), but I would recommend creating an auxiliary class GradeBookEntry, which would hold the actual details of the student records, rather than having a series of parallel arrays which need to be synchronized manually.

class GradeBookEntry {

    final static int EXAMS = 4;
    String name;
    double[] scores;
    char letterGrade;

    public GradeBookEntry(String student) {
        name = student;
        scores = new double[EXAMS];
    }

    public void setName(int studentNumber, String student) 
    { 
        name = student; 
    } 

    public void setScores(double[] scores) 
    { 
            scores = copyArray(scores); 
    } 

    public static double[] copyArray(double[] from) 
    { 

        double[] to = new double[from.length]; 
        for (int i = 0; i <from.length; i++) 
            to[i]=from[i]; 
        return to; 
    } 

    public String getName()  
    { 
        return name; 
    } 

    public double getAverage()  
    { 
        double total = 0.0; 
        double average = 0.0;  

        for (int row = 0; row < EXAMS; row++) {
            total += scores[row]; 
        }
        average = total / EXAMS; 

        return average;
    } 

    public static void getLetterGrade(int i)  
    { 
        double grade; 
        double average = 0; 
        if (average > 90) 
            grade = 'A'; 
        else if (average > 80) 
            grade = 'B'; 
        else if (average > 70) 
            grade = 'C'; 
        else if (average > 60) 
            grade = 'D'; 
        else grade = 'F'; 
    }  
}

You can see how unloading the details of the GardeBook into GradeBookEntry simplifies much of the code; the GradeBook class itself becomes just:

public class GradeBook {
    finalstatic int STUDENTS = 5;

    public GradeBook() {
        GradeBookEntry[] students = new GradeBookEntry[STUDENTS];
    }

    public GradeBookEntry getStudent(int i) {
        return students[i - 1];
    }

    public double getClassAverage() {
        double total = 0; 
        double average = 0;

        for (int i = 0; i < STUDENTS; i++) {
            total += student[i].getAverage();
        }

        average = total / STUDENTS;
        return average;
    }
}

You'll note that this version fixes the problem, because it has a constructor which allocates the array, which was what your code was missing - you never allocated the array for names..

Edited 3 Years Ago by Schol-R-LEA

It is usually very simple to track down the cause of a NullPointerException compared to most exceptions. It just means that some reference was null when an object was required, so all you need to do is go to the line in your source code that most directly caused the problem and then look for a reference that might be null. The line you are looking for is the line that is closest to the top of the stack trace, ignoring lines that aren't in your source code. In this case:

 at defaultpackage.GradeBook.setName(GradeBook.java:25)

And if you look at that line there are only two references, and only one of those references needs to be an object. As simply as that, you have found the cause of your problem.

This article has been dead for over six months. Start a new discussion instead.