[英]java.lang.NullPointerException when setting value of attributes within a loop
如果用户键入“end”,则在第二个输入“输入学生的名字”中尝试这样做,循环自动为数组中的每个 object 分配 id 和 name 的“null”属性和 0年龄和身份证,以及打破外环。 但是,我收到错误 java.lang.NullPointerException。 任何帮助,将不胜感激。
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;
}
}
您在这里失败了,因为您在初始化Studentz
数组的所有元素之前尝试打印学生数据:
for (int c = 0; c < numberof; ++c) {
System.out.println(Studentz[c].Snake());
}
您的代码也因同样的原因在这里失败:
for (int g = i; g < numberof; ++g) {
Studentz[g].Setfirst("null"); // NPE - no Student created yet in the array
一些可能有用的提示:
遵循 Java 变量和方法名称的命名规则, Studentz
应该是studentz
,即使对于您的 Arrays 也是如此。 我知道...你厌倦了阅读,但随着你的进步,你会看到它真的是多么有益。
如果可以,请不要使用多个Scanner对象,在您的用例中不需要这样做。 声明一台扫描仪 object 并坚持下去。 您这样做可能是因为您在nextInt( ) 方法之后使用了nextLine()方法,并且您发现它跳过了名字提示并提供了 Null 字符串 ("")。 发生这种情况是因为 nextInt() 方法在按下 Enter键时不使用换行符。 要解决此问题,您可以将代码行myObj.nextLine();
直接下int numberof = myObj.nextInt();
代码行:
int numberof = myObj.nextInt();
myObj.nextLine(); // Consume ENTER key hit
或者根本不使用nextInt()方法。 而是坚持使用nextLine()方法而不用担心消耗:
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循环中。 给用户一个正确输入的机会,毕竟,错字确实会发生。
去掉外环: label。 事实上,如果可以的话,尽量避免使用它们……而且可以。 它只会在您可能需要一个相对罕见的场合。
至少在某种程度上,给你的变量起有意义的名字。 当您以后想在将来阅读旧代码时,这可以使您受益。
在您的Student class 中,您为自己创建了一个名为Studentss()
的非常好的方法。 好吧,我认为它应该是一个构造函数,并为调用 Setter 方法节省大量代码条目。 毕竟,这主要是构造函数的用途。 您的 Student class 构造函数可能如下所示:
public Student(String firstName, String lastName, int age, int id) {
this.first = firstName;
this.last = lastName;
this.age = age;
this.id = id;
}
并被这样使用。 您会注意到,在外部for循环的每次迭代中,所有提示答案都放在变量中,然后在所有这些提示的末尾使用构造函数实例化一个学生 object,例如:
studentz[i] = new Student(firstname, lastname, age, id);
这样做意味着不需要调用 Setter 方法。 进行 setter 调用没有任何问题,只是使用构造函数更容易。 如下所示:
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());
}
snake()方法实际上只是另一个toString()方法,这并没有什么问题,但是您可能需要考虑使用StringBuilder class 来创建返回的字符串,而不是进行连接,例如:
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();
}
这里不是很重要,但如果您对许多大字符串进行大量连接,它可以为您节省 memory。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.