我有这个班,Party,我有一个arraylist
回复和arraylist
受邀。我们的目标是,我们应该能够使用arraylists
为这些addInvited()
添加名称,并使用getInvited()
获取该名称。我知道问题出在这两种方法之一,因为其他方法都已通过测试。我需要这样做,以便有人可以使用addInvited()添加一个Person对象,但该人不能更改他的名字。我似乎无法弄清楚我是不是制作了足够深的副本,或者是什么......
package lab04partB;
import java.util.ArrayList;
public class Party {
private ArrayList<Person> invited;
private ArrayList<Person> RSVP;
public Party() {
invited = new ArrayList<Person>();
RSVP = new ArrayList<Person>();
}
public void addInvited(Person person) {
if (!invited.contains(person)) {
Person JohnDoe = new Person(person.getName());
invited.add(JohnDoe);
}
}
public ArrayList<Person> getInvited() {
ArrayList<Person> tempList = new ArrayList<Person>(invited);
return tempList;
}
public void addRSVP(Person person) {
if ((!RSVP.contains(person)) && (invited.contains(person))) {
Person JaneDoe = new Person(person.getName());
RSVP.add(JaneDoe);
}
}
public ArrayList<Person> getRSVP() {
ArrayList<Person> tempList = new ArrayList<Person>(RSVP);
return tempList;
}
}
如果它有帮助,这是它正在运行的测试!
@Test
public void testGetInvitedModifyNamesReturned() {
Party party = new Party();
Person a = new Person( new String( KANY_GARCIA ));
Person b = new Person( new String( LAURA_PAUSINI ));
party.addInvited( a );
party.addInvited( b );
ArrayList<Person> list = party.getInvited();
assertEquals( 2, list.size() );
for (Person p : list) {
p.setName( new String( MIGUEL_RIOS ));
}
list = party.getInvited();
assertEquals( "Incorrect result", 2, list.size() );
assertTrue ( "Incorrect result", list.contains( a ));
assertTrue ( "Incorrect result", list.contains( b ));
}
答案 0 :(得分:0)
一种方法是在name
类Person
中创建final
字段,但之后任何人都无法更改任何人的姓名。猜猜那不是你想要的。
或者,您可以在Party
中创建子类Person
的内部类,并禁止更改名称。然后,当您将一个人添加到一方时,您首先将输入参数转换为不可变的人。
class Party {
private static final class ImmutablePerson extends Person {
public ImmutablePerson(String name) {
super(name);
}
@Override
void setName(String s) {
throw new RuntimeException("Cannot change name");
// or just do nothing here
}
}
public void addInvited(Person person) {
ImmutablePerson immutable = new ImmutablePerson(person.getName());
if (!invited.contains(immutable)) {
invited.add(immutable);
}
}
}
答案 1 :(得分:0)
制作Person
immutable。这实际上也是最佳实践,因为人们不会更改数据,并且(如此处)您可以安全地发布它们。
答案 2 :(得分:0)
有几种方法可以做到这一点......
您可以使用接口来维护API的合同期望,因此您可以设置Person
(带有getter)和可变版本(带有setter)的非可变版本,这意味着您的{{ 1}} class可以返回非可变类型,阻止人们直接修改值。
这可能导致使用非可变实例作为可变版本的包装器,进一步阻止人们投射结果来解决这个问题。
像...一样的东西。
Party
然后你的public interface Person extends Comparable<Person> {
public String getName();
}
public class DefaultPerson implements Person {
private String name;
public DefaultPerson(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (!(obj instanceof Person)) {
return false;
}
final Person other = (Person) obj;
if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) {
return false;
}
return true;
}
@Override
public int hashCode() {
int hash = 3;
hash = 37 * hash + Objects.hashCode(this.name);
return hash;
}
@Override
public int compareTo(Person arg0) {
return arg0.getName().compareTo(name) * -1;
}
public Character[] toCharacterArray(String s) {
if (s == null) {
return null;
}
int len = s.length();
Character[] array = new Character[len];
for (int i = 0; i < len; i++) {
array[i] = new Character(s.charAt(i));
}
return array;
}
@Override
public String toString() {
return getName();
}
}
可能看起来像......
Party
该类只知道处理public static class Party {
private ArrayList<Person> invited;
private ArrayList<Person> RSVP;
public Party() {
invited = new ArrayList<Person>();
RSVP = new ArrayList<Person>();
}
public void addInvited(Person person) {
if (!invited.contains(person)) {
invited.add(person);
}
}
public List<Person> getInvited() {
return Collections.unmodifiableList(invited);
}
public void addRSVP(Person person) {
if ((!RSVP.contains(person)) && (invited.contains(person))) {
RSVP.add(person);
}
}
public List<Person> getRSVP() {
return Collections.unmodifiableList(RSVP);
}
}
类型,这些类型不可变(好吧,您可以创建Person
的实例并将它们添加到列表中,这会阻止调用者修改名称,但这取决于你)
该类还使用DefaultPerson
来阻止调用者修改Collections.unmodifiableList
!奖金:)
这意味着,做一些像......
List
是不可能的,因为List<Person> list = party.getInvited();
for (Person p : list) {
p.setName(new String("Whelma"));
}
不是setName
的方法!
这可能超出了您的作业范围,相反,当您返回被邀请者列表时,您可以创建值的新实例,例如......
Person
这不是最佳选择,但它允许您的代码通过您拥有的测试。
我还应该指出,public void addInvited(Person person) {
if (!invited.contains(person)) {
invited.add(person);
}
}
public ArrayList<Person> getInvited() {
ArrayList<Person> tempList = new ArrayList<>(invited.size());
for (Person p : invited) {
tempList.add(new Person(p.getName()));
}
return tempList;
}
与来自JavaDocs的equals
有合同关系:
请注意,通常需要在重写此方法时覆盖hashCode方法,以便维护hashCode方法的常规协定,该方法声明相等的对象必须具有相同的哈希代码。
基本上,这意味着,如果你覆盖hashcode
,你还必须覆盖equals
(反之亦然)