Reputation: 1124
I have two classes: Apartments and Building. The Apartment class:
public class Apartment {
private String familyName;
private int rent;
private boolean isRented;
}
The Building class has an Apartment array, and a numOfApartments variable which indicates how many apartments the building has, and also a FINAL variable who indicates the max number for apartments in one building.
private Apartment[] apartments;
private int numOfApartments;
private final int MAX_APARTMENTS=20;
public Building() {
this.apartments=new Apartment[MAX_APARTMENTS];
this.numOfApartments=0;
}
Now I want to make a method which raises the rent for an apartment by an amount which is taken as parameter:
public void raiseRent(int amount) {
for (int i=0; i<numOfApartments; i++) {
apartments[i].setRent(apartments[i].getRent() + amount);
}
}
the addAppartment method:
public boolean addApartment(Apartment a){ //adds an appartment to the building if
//there's enough space in the array.
if (this.numOfApartments<this.MAX_APARTMENTS)
{
this.apartments[this.numOfApartments]=new Apartment(a);
this.numOfApartments++;
return true;
}
return false;
}
The apartment class string ToString method:
public String toString()
{
if (this.isRented) //if the apartment is rented, prints:
{
return "Apartment rent: " + this.rent + ". rented to " + this.familyName + " family.";
}
else
return "Apartment rent: " + this.rent + ". not rented yet.";
}
The main is:
String familyName; int rent;
System.out.println("enter family name and rent by this order");
familyName=scan.next();
rent=scan.nextInt();
Apartment a=new Apartment(familyName,rent); //build new apartment object.
Building b=new Building();
System.out.println(b.addApartment(a));
b.raiseRent(200); //initiate the raiseRent method.
Everything here works, but when I write this:
System.out.println(a);
The rent is shown as the old rent, not the updated one. When I write this:
System.out.println(b.apartments[0]);
It works.
Why when I write System.out.println(a); it doesn't work?
Thank you for the answer.
Upvotes: 0
Views: 249
Reputation: 726569
The problem is in your addApartment
method: rather than adding the Apartment
object passed in to the array, you add a brand-new object created with new
by calling a copy constructor. This breaks the connection between the variable called a
that you passed in and the element at index zero of the apartments
array, explaining the difference in printed values.
The copy semantic that you have in the addApartment
is actually a good thing: it saves you from unusual aliasing later on, because the implementation is no longer dependent on the callers to pass distinct objects. Changing the code to
apartments[this.numOfApartments] = a; // No copy
creates problems, because Apartment
is mutable. Consider this call sequence:
Apartment a = new Apartment();
for (int i = 100 ; i <= 1000 ; i += 100) {
a.setRent(i);
building.addApartment(a);
}
One would expect ten apartments, with rents 100 to 1000 to be added. With a no-copy change, however, you would end up with ten identical apartments, all with rent set to 1000. This is because under the hood all ten items in the apartment
array would reference the same Apartment
object - the one you created before the for
loop. This causes numerous headaches down the road, so it is better to keep the copying code in place, and know that rent increases should be checked on the objects inside the building, not on the objects that you passed into the addApartment
method.
Upvotes: 1
Reputation: 4544
In your
public boolean addApartment(Apartment a)
method:
this.apartments[this.numOfApartments]=new Apartment(a);
Creates a new apartment which appears to be constructed from an existing apartment. This is a copy.
After you raise the rent, the
Apartment a=new Apartment(familyName,rent); //build new apartment object.
That you passed in to
b.addApartment(a)
Will not have an updated rent. This is because Java is pass-by-value. It's a "new" int
in the new Apartment
your Building Apartment[]
collection contains, even if you set it from an existing one (this.rent = other.rent
)
Upvotes: 1