Assaf
Assaf

Reputation: 1124

Java Objects: Method doesn't print as it should

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

Answers (2)

Sergey Kalinichenko
Sergey Kalinichenko

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

Doug Moscrop
Doug Moscrop

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

Related Questions