En essayant de faire en sorte que si l'utilisateur tape "fin", dans la deuxième entrée qui est "Entrez le prénom de l'étudiant", la boucle attribue automatiquement à chaque objet du tableau les attributs de "null" pour id et nom, et 0 pour l'âge et l'identité, ainsi que la rupture de la boucle extérieure. Cependant, j'obtiens l'erreur java.lang.NullPointerException. Toute aide serait appréciée.

import java.util.*;


class Main {
    public static void main(String[] args) {
        Scanner myObj = new Scanner(System.in);
        System.out.println("Enter number of students");
        int numberof = myObj.nextInt();
        System.out.println("Number of students is " + numberof);
        Student Studentz[] = new Student[numberof];
        outerloop:
            for (int i = 0; i < numberof; ++i) {
                Studentz[i] = new Student();

                System.out.println("Enter first name of student " + (i + 1));
                Scanner myObj1 = new Scanner(System.in);

                String firstname = myObj1.nextLine();
                System.out.println("Firstname is: " + firstname);
                if (firstname.equals("end")) {
                    for (int g = i; g < numberof; ++g) {
                        Studentz[g].Setfirst("null");
                        Studentz[g].Setlast("null");
                        Studentz[g].Setage(0);
                        Studentz[g].Setid(0);
                    }
                    break outerloop;
                } else {
                    Studentz[i].Setfirst(firstname);

                    System.out.println("Enter last name of student " + (i + 1));
                    Scanner myObj2 = new Scanner(System.in);

                    String lastname = myObj2.nextLine();

                    System.out.println("Last name is: " + lastname);
                    Studentz[i].Setlast(lastname);;

                    System.out.println("Enter age of student " + (i + 1));
                    Scanner myObj3 = new Scanner(System.in);

                    int nazca = myObj3.nextInt();
                    System.out.println("Age is: " + nazca);
                    Studentz[i].Setage(nazca);


                    System.out.println("Enter ID of student " + (i + 1));
                    Scanner myObj4 = new Scanner(System.in);

                    int nazca1 = myObj4.nextInt();
                    System.out.println("ID is: " + nazca1);
                    Studentz[i].Setid(nazca1);

                }

                for (int c = 0; c < numberof; ++c) {
                    System.out.println(Studentz[c].Snake());
                }
            }
    }
}

public class Student {
    private String first;
    private String last;
    private int age;
    private int id;
    public int getid() {
        return
        this.id;
    }


    public void Studentss(String f, String l, int a, int i) {
        first = f;
        last = l;
        age = a;
        id = i;
    }
    public void Setfirst(String z) {
        this.first = z;
    }
    public void Setlast(String za) {
        this.last = za;
    }
    public void Setage(int zb) {
        this.age = zb;
    }
    public void Setid(int zc) {
        this.id = zc;
    }
    public String Snake() {
        String snek = "Name is " + this.first + " " + this.last + " , Age is " + this.age + " ,ID is " + this.id;
        return snek;
    }
}
-1
Kai 24 avril 2020 à 21:34

2 réponses

Meilleure réponse

Vous échouez ici car vous essayez d'imprimer les données des élèves avant d'initialiser tous les éléments du tableau Studentz:

for (int c = 0; c < numberof; ++c) {
    System.out.println(Studentz[c].Snake());
}

Aussi votre code échoue ici pour la même raison:

for (int g = i; g < numberof; ++g) {
    Studentz[g].Setfirst("null");  // NPE - no Student created yet in the array

1
Alex Rudenko 24 avril 2020 à 19:06

Quelques conseils utiles:

Suivez les règles de dénomination Java pour vos variables et noms de méthodes, Studentz devrait être studentz, même pour vos tableaux. Je sais ... tu en as marre de lire ça mais au fur et à mesure que tu progresses, tu verras à quel point c'est vraiment bénéfique.

Si vous le pouvez, n'utilisez pas plusieurs objets Scanner , cela n'est pas nécessaire dans votre cas d'utilisation. Déclarez un objet Scanner et respectez-le. Vous faites probablement cela parce que vous utilisez la méthode nextLine () après la méthode nextInt () et que vous constatez qu'elle ignore l'invite du prénom et fournit un Chaîne nulle (""). Cela se produit car la méthode nextInt () ne consomme pas le caractère de nouvelle ligne lorsque la touche Entrée est appuyée. Pour résoudre ce problème, vous devez soit placer la ligne de code myObj.nextLine(); directement sous la ligne de code int numberof = myObj.nextInt();:

int numberof = myObj.nextInt();
myObj.nextLine();  // Consume ENTER key hit

Ou n'utilisez pas du tout la méthode nextInt () . Au lieu de cela, tenez-vous en à la méthode nextLine () et ne vous inquiétez pas de la consommation:

Scanner myObj = new Scanner(System.in);
int numberof = 0;
String val = "";
while (val.equals("")) {
    System.out.println("Enter number of students");
    val = myObj.nextLine();
    if (!val.matches("\\d+")) {
        System.err.println("Invalid number supplied!");
        val = ""; 
        continue;
    }
    numberof = Integer.parseInt(val);
}
System.out.println("Number of students is " + numberof);
Student[] studentz = new Student[numberof];

C'est toujours une bonne idée de valider toute entrée de l'utilisateur (comme indiqué ci-dessus), même si elle se trouve dans une boucle for . Donnez à l'utilisateur la possibilité de faire une entrée correcte, après tout, des fautes de frappe se produisent.

Supprimez le libellé OutsideLoop: . En fait, essayez d'éviter de les utiliser si vous le pouvez ... et vous le pouvez. Ce ne serait que dans une occasion relativement rare où vous pourriez en avoir besoin.

Donnez à vos variables des noms significatifs, au moins dans une certaine mesure. Cela peut vous être bénéfique plus tard, lorsque vous souhaitez lire votre ancien code à l'avenir.

Dans votre classe Étudiant , vous avez créé vous-même une méthode très intéressante nommée Studentss(). Eh bien, je pense que cela devrait être un constructeur à la place et vous épargner beaucoup d'entrée de code pour les appels aux méthodes Setter. Après tout, c'est surtout à cela que sert le constructeur. Votre constructeur de classe Student peut ressembler à ceci:

public Student(String firstName, String lastName, int age, int id) {
    this.first = firstName;
    this.last = lastName;
    this.age = age;
    this.id = id;
}

Et être utilisé comme ça. Vous remarquerez qu'à chaque itération de la boucle externe for , toutes les réponses aux invites sont placées dans des variables puis à la fin de toutes ces invites, le constructeur est utilisé pour instancier un objet étudiant, par exemple:

studentz[i] = new Student(firstname, lastname, age, id); 

Cela signifie qu'il n'est pas nécessaire de faire des appels aux méthodes Setter. Il n'y a rien de mal à faire des appels de setter, c'est juste plus facile d'utiliser le constructeur. Ceci est démontré ci-dessous:

Scanner myObj = new Scanner(System.in);

int numberof = 0;
String val = "";
while (val.equals("")) {
    System.out.println("Enter number of students");
    val = myObj.nextLine();
    if (!val.matches("\\d+")) {
        System.err.println("Invalid number supplied!");
        val = "";
        continue;
    }
    numberof = Integer.parseInt(val);
}
System.out.println("Number of students is " + numberof);

Student[] studentz = new Student[numberof];

for (int i = 0; i < numberof; ++i) {
    String firstname = "null";
    String lastname = "null";
    int age = 0;
    int id = 0;
    boolean exitOuterForLoop = false;

    // Student First Name Prompt:
    // (with option to End and default remaining to null's and 0's)
    while (firstname.equals("null")) {
        System.out.println("Enter first name of student " + (i + 1) + " (End to stop):");
        firstname = myObj.nextLine();
        if (firstname.equalsIgnoreCase("end")) {
            firstname = "null";
            //Make all remaining Student instances null and 0
            for (int g = i; g < numberof; ++g) {
                studentz[g] = new Student(firstname, lastname, age, id); // Use Student class constructor
            }
            exitOuterForLoop = true;
            break; // Exit this 'while' loop
        }
        // Validate first name (no numbers or crazy characters)
        if (!firstname.matches("(?i)[a-z']+")) {
            System.err.println("Invalid First Name! (" + firstname + ") Try Again...");
            firstname = "null";
        }
    }
    if (exitOuterForLoop) {
        break; // Exit this outer 'for' loop.
    }
    System.out.println("Firstname is: " + firstname);

    // Student Last Name Prompt
    while (lastname.equals("null")) {
        System.out.println("Enter last name of student " + (i + 1));
        lastname = myObj.nextLine();
        // Validate last name (no numbers or crazy characters)
        if (!lastname.matches("(?i)[a-z']+")) {
            System.err.println("Invalid Last Name! (" + lastname + ") Try Again...");
            lastname = "null";
        }
    }
    System.out.println("Last name is: " + lastname);

    // Student Age Prompt
    val = "";
    while (val.equals("")) {
        System.out.println("Enter age of student " + (i + 1));
        val = myObj.nextLine();
        // Validate age (digits 0 to 9 only)
        if (!val.matches("\\d+")) {
            System.err.println("Invalid Age Supplied! (" + val + ") Try Again...");
            val = "";
        }
    }
    age = Integer.parseInt(val);
    System.out.println("Student age is: " + age);

    // Student ID Prompt
    val = "";
    while (val.equals("")) {
        System.out.println("Enter ID of student " + (i + 1));
        val = myObj.nextLine();
        // Validate age (digits 0 to 9 only)
        if (!val.matches("\\d+")) {
            System.err.println("Invalid ID Supplied! (" + val + ") Try Again...");
            val = "";
        }
    }
    id = Integer.parseInt(val);
    System.out.println("Student ID is: " + id);

    studentz[i] = new Student(firstname, lastname, age, id); // Use Student class constructor
}

// Display the instances of Student contained within the 'studentz[]' array.
for (int c = 0; c < numberof; ++c) {
    System.out.println(studentz[c].toString());
}

La méthode snake () est en fait juste une autre méthode toString () et il n'y a rien de mal à cela, mais vous pouvez envisager d'utiliser la classe StringBuilder pour créer la chaîne retournée plutôt que de faire des concaténations, par exemple:

public String snake() {
    return new StringBuilder("Name is ").append(this.first).append(" ").append(this.last)
                            .append(" , Age is ").append(this.age).append(" , ID is ")
                            .append(this.id).toString();
}

Pas trop important ici, mais cela peut vous faire économiser de la mémoire si vous faites beaucoup de concaténation avec de nombreuses grandes chaînes.

1
DevilsHnd 24 avril 2020 à 21:50