This question already has an answer here:
这个问题在这里已有答案:
为什么我的ArrayList包含添加到列表中的最后一项的N个副本? 4个答案
Beginner, be kind.
初学者,善待。
Whenever I add to the arraylist through the "Add Person", it overwrites the previous entry. So when I run sort, I then get two of the exact same entries which is whichever was typed in last. How do I fix this? What do I do?
每当我通过“添加人”添加到arraylist时,它会覆盖前一个条目。因此,当我运行sort时,我会获得两个完全相同的条目,这些条目是最后输入的。我该如何解决?我该怎么办?
Here is my class file:
这是我的班级文件:
import java.util.Calendar;
import java.util.Date;
import java.text.*;
public class Person implements Comparable {
private static int totalNumber;
public static int getTotal() {
// Returns total number of employees
return totalNumber;
}
private String fName;
private String lName;
private Date lastModified;
private String address;
private String city;
private String state;
private String zip;
private String phone;
public Person(String fName, String lName, String address, String city,
String state, String zip, String phone) {
this.fName = fName;
this.lName = lName;
this.address = address;
this.city = city;
this.state = state;
this.zip = zip;
this.phOne= phone;
Calendar calobj = Calendar.getInstance();
this.lastModified = calobj.getTime();
}
public String getfName() {
return this.fName;
}
public void setfName(String fName) {
this.fName = fName;
}
public String getlName() {
return this.lName;
}
public void setlName(String lName) {
this.lName = lName;
}
public Date getLastModified() {
return this.lastModified;
}
public void setLastModified(Date lastModified) {
this.lastModified = lastModified;
}
public String getAddress() {
return this.address;
}
public void setAddress(String address) {
this.address = address;
}
public String getCity() {
return this.city;
}
public void setCity(String city) {
this.city = city;
}
public String getState() {
return this.state;
}
public void setState(String state) {
this.state = state;
}
public String getZip() {
return this.zip;
}
public void setZip(String zip) {
this.zip = zip;
}
public String getPhone() {
return this.phone;
}
public void setPhone(String phone) {
this.phOne= phone;
}
@Override
public String toString() {
DateFormat df = new SimpleDateFormat("dd/MM/yy HH:mm:ss");
return "\n First Name= " + fName + "\n Last Name= " + lName
+ "\n Address= " + address + "\n City= " + city + "\n State= "
+ state + "\n Zip= " + zip + "\n PhOne= " + phone
+ "\n Last Modified= " + df.format(lastModified);
}
@Override
public int compareTo(Object other) {
// TODO Auto-generated method stub
return this.lName.compareToIgnoreCase(((Person) other).lName);
}
}
Here is my test file:
这是我的测试文件:
import java.util.*;
public class testAddressBook {
public static void main(String[] args) {
// TODO Auto-generated method stub
ArrayList addressBook = new ArrayList();
Person newPerson = new Person(null, null, null, null, null, null, null);
@SuppressWarnings("resource")
Scanner sc = new Scanner(System.in);
boolean switcher = true;
do {
System.out.println("\n\tAddress Book Menu");
System.out.println("\n\t\tEnter A to (A)dd Person ");
System.out.println("\t\tEnter D to (D)elete Person");
System.out.println("\t\tEnter M to (M)odify Person");
System.out.println("\t\tEnter S to (S)earch Address Book ");
System.out.println("\t\tEnter L to (L)ist ALL (sorted) ");
System.out.println("\t\tEnter Q to Quit");
System.out.print("\n\tPlease enter your choice: ");
char choice = sc.nextLine().toUpperCase().charAt(0);
while ((choice != 'A') && (choice != 'D') && (choice != 'M')
&& (choice != 'S') && (choice != 'L') && (choice != 'Q')) {
System.out
.println("Invalid choice! Please select (A)dd, (D)elete, (M)odify, (S)earch, (L)ist or (Q)uit: ");
choice = sc.nextLine().toUpperCase().charAt(0);
}
switch (choice) {
case 'A':
System.out.println("\nTo add a person, follow the prompts.");
System.out.print("\nEnter First Name: ");
newPerson.setfName(sc.nextLine());
System.out.print("\nEnter Last Name: ");
newPerson.setlName(sc.nextLine());
System.out.print("Enter Address: ");
newPerson.setAddress(sc.nextLine());
System.out.print("Enter City: ");
newPerson.setCity(sc.nextLine());
System.out.print("Enter State: ");
newPerson.setState(sc.nextLine());
System.out.print("Enter Zip: ");
newPerson.setZip(sc.nextLine());
System.out.print("Enter Phone Number: ");
newPerson.setPhone(sc.nextLine());
addressBook.add(newPerson);
System.out
.println("\nYou have successfully added a new person!");
break;
case 'D':
break;
case 'M':
break;
case 'S':
Collections.sort(addressBook);
for (int i = 0; i
You need to instantiate a new Person in the loop. For example declare:
您需要在循环中实例化一个新Person。例如声明:
Person newPerson;
And then in while loop instantiate it:
然后在while循环实例化它:
switch (choice) {
case 'A' :
System.out.println("\nTo add a person, follow the prompts.");
newPerson = new Person(null, null, null, null, null, null, null);
.... so on
If you also instantiate it out of the loop as well it leads to creation of one extra object.
如果你也将它从循环中实例化,那么它会导致创建一个额外的对象。
You have to create a new instance of Person
for every iteration of the loop. Otherwise, you are just updating the same Person all over again.
您必须为循环的每次迭代创建一个Person的新实例。否则,您只是重新更新同一个人。
Move this line into the do
loop:
将此行移动到do循环中:
Person newPerson = new Person(null, null, null, null, null, null, null);
Over even better, make a private
method that returns a new Person and have something like
甚至更好,制作一个私有方法,返回一个新的Person,并有类似的东西
addressBook.add(readNewPerson(sc));
System.out.println("\nYou have successfully added a new person!");
You create your Person only one times:
您只创建一次您的Person:
Person newPerson = new Person(null, null, null, null, null, null, null);
And you override the properties in every loop. You have to create a new person in your loop:
并且您在每个循环中覆盖属性。您必须在循环中创建一个新人:
do {
System.out.println("\n\tAddress Book Menu");
System.out.println("\n\t\tEnter A to (A)dd Person ");
System.out.println("\t\tEnter D to (D)elete Person");
System.out.println("\t\tEnter M to (M)odify Person");
System.out.println("\t\tEnter S to (S)earch Address Book ");
System.out.println("\t\tEnter L to (L)ist ALL (sorted) ");
System.out.println("\t\tEnter Q to Quit");
System.out.print("\n\tPlease enter your choice: ");
char choice = sc.nextLine().toUpperCase().charAt(0);
while ((choice != 'A') && (choice != 'D') && (choice != 'M') && (choice != 'S') && (choice != 'L')&& (choice != 'Q')) {
System.out.println("Invalid choice! Please select (A)dd, (D)elete, (M)odify, (S)earch, (L)ist or (Q)uit: ");
choice = sc.nextLine().toUpperCase().charAt(0);
}
switch (choice) {
case 'A' :
System.out.println("\nTo add a person, follow the prompts.");
Person newPerson = new Person(null, null, null, null, null, null, null);
....
`Person newPerson = new Person();//define a default constructor
. . . .
System.out.print("Enter Phone Number: ");
newPerson.setPhone(sc.nextLine());
addressBook.add(newPerson);`
You need to create a new person in side a loop and set his attributes, finally add the person to list.
您需要在循环中创建一个新人并设置其属性,最后将该人员添加到列表中。
You are reusing the newPerson
object over and over, just rewriting the internal fields. In Java an object (rather than primitive) variable is a named reference to an object, so every time you do addressBook.add(newPerson)
you are adding the same object to the list (this is allowed because it's not a Set
). You are not copying newPerson
into the list, you are just making the nth position in the list point to newPerson
.
您正在重复使用newPerson对象,只需重写内部字段。在Java中,对象(而不是原始)变量是对象的命名引用,因此每次执行addressBook.add(newPerson)时,都会将相同的对象添加到列表中(这是允许的,因为它不是Set)。您没有将newPerson复制到列表中,只是将列表中的第n个位置指向newPerson。
The minimal change would be to move the object constructor call as Thilo suggests, but I strongly agree with his further suggestion that you should be using a dedicated method for each case. In that case, your whole problem disappears neatly due to scope of the local variable. In general you should structure your programs so that they make sense and are readable (rather than being a monolithic main
procedure) and as a direct consequence all sorts of bugs just never happen.
最小的改变是移动对象构造函数调用Thilo建议,但我非常同意他的进一步建议,即你应该为每个案例使用专用方法。在这种情况下,由于局部变量的范围,整个问题会整齐地消失。一般来说,你应该构建你的程序,使它们有意义和可读(而不是一个单一的主程序),直接的结果是各种各样的错误永远不会发生。
See also:
What's the difference between passing by reference vs. passing by value?
传递参考与传递值之间有什么区别?