I have a ParkingLot class with a getEmptySpaces() method that applies to ParkingLot objects, which are arrays of Car objects.
I want to call lot.getEmptySpaces(), but my IDE, Netbeans, throws a fit if I give it an array rather than a specific item. lot[1].getEmptySpaces() compiles fine, but crashes when it runs, as expected, since it's supposed to receive an array, not a null.
How do I call a method on an array defined by the same class?
// Main
ParkingLot[] lot = new ParkingLot[10];
lot[1].getEmptySpaces(); // compiles but doesn't run
lot.getEmptySpaces(); // what i want to run but doesn't
// Car class
public class Car {
private String color;
private String licensePlate; // lp #
public Car(String color, String licensePlate) {
this.color = color;
this.licensePlate = licensePlate;
}
/**
* #return the color
*/
public String getColor() {
return color;
}
/**
* #param color the color to set
*/
public void setColor(String color) {
this.color = color;
}
/**
* #return the licensePlate
*/
public String getLicensePlate() {
return licensePlate;
}
/**
* #param licensePlate the licensePlate to set
*/
public void setLicensePlate(String licensePlate) {
this.licensePlate = licensePlate;
}
#Override
public String toString() {
return "Car{" + "color=" + color + ", licensePlate=" + licensePlate + '}';
}
}
// ParkingLot class
public class ParkingLot {
private Car[] spaces; // lp=000000 color=none will represent an empty space
private int currentIndex;
/**
* Creates a parkingLot object
*
* #param size how many spaces are needed in the parking lot
*/
public ParkingLot(int size) {
// Array Example: String[] arr = new String[20];
this.spaces = new Car[size];
this.currentIndex = 0;
}
public int getEmptySpaces(){
int emptySpaces = 0;
for(int i = 0; i < spaces.length; i++){
if (spaces[i] == null){
emptySpaces++;
}
}
return emptySpaces;
}
/**
* Adds a car to the parking lot
*
* #param car the car to be added to the parking lot
*/
public void addCar(Car car){
spaces[currentIndex] = car;
currentIndex++;
}
}
ParkingLot[] lot = new ParkingLot[10];
It feels like you imagine this creates a single parking lot with 10 spaces.
It doesn't.
It creates a plot of land upon which up to 10 parking lots can be placed, though none are there yet (a ParkingLot is an object, if you want one to exist, somebody, somewhere, must invoke new ParkingLot(), or no parking lot objects exist).
lot[1].getEmptySpaces()
This goes to the second lot (java is 0-indexed, so, lot[1] is the second lot), and asks it: Oi, how much free space is there? Given that you're yelling this at an empty space where a parking lot can be, but isn't, you get a NullPointerException.
lot.getEmptySpaces();
This makes no sense at all. How can you ask 10 parking lots at once? Even worse, how can you ask a bit of terrain reserved for 10 parking lots, but where no lots exist right now?
Relevant:
for (int i = 0; i <lots.size; i++) lots[i] = new ParkingLot();
The problem I was having was that I created an array of ParkingLot objects. I only needed one ParkingLot, not 10.
My code should have been:
ParkingLot lot = new ParkingLot[10];
Instead of:
ParkingLot[] lot = new ParkingLot[10];
It was just a typo, like usual.
Related
I'm sitting on an assignment for university and I'm at a point, where I fear I haven't really understood something fundamental in the concecpt of Java or OOP altogether. I'll try to make it as short as possible (maybe it's sufficient to just look at the 3rd code segment, but I just wanted to make sure, I included enough detail). I am to write a little employee management. One class within this project is the employeeManagement itself and this class should possess a method for sorting employees by first letter via bubblesort.
I have written 3 classes for this: The first one is "Employee", which contains a name and an ID (a running number) , getter and setter methods and one method for checking whether the first letter of one employee is smaller (lower in the alphabet) than the other. It looks like this:
static boolean isSmaller(Employee source, Employee target) {
char[] sourceArray = new char[source.name.length()];
char[] targetArray = new char[target.name.length()];
sourceArray = source.name.toCharArray();
targetArray = target.name.toCharArray();
if(sourceArray[0] < targetArray[0])
return true;
else
return false;
}
I tested it and it seems to work for my case. Now there's another class called EmployeeList and it manages the employees via an array of employees ("Employee" objects). The size of this array is determined via constructor. My code looks like this:
public class EmployeeList {
/*attributes*/
private int size;
private Employee[] employeeArray;
/* constructor */
public EmployeeList(int size) {
this.employeeArray = new Employee[size];
}
/* methods */
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
/* adds employee to end of the list. Returns false, if list is too small */
boolean add(Employee m) {
int id = m.getID();
if (id > employeeArray.length) {
return false;
} else {
employeeArray[id] = m;
return true;
}
}
/* returns employee at certain position */
Employee get(int index) {
return employeeArray[index];
}
/* Sets employee at certain position. Returns null, if position doesn't exist. Else returns old value. */
Employee set(int index, Employee m) {
if (employeeArray[index] == null) {
return null;
} else {
Employee before = employeeArray[index];
employeeArray[index] = m;
return before;
}
}
Now comes my real problem: In a third class called "employeeManagement" I am supposed to implement the sorting algorithm. The class looks like this:
public class EmployeeManagement {
private EmployeeList ml = new EmployeeList(3);
public boolean addEmployee(Employee e) {
return ml.add(e);
}
public void sortEmployee() {
System.out.println(ml.getSize()); // I wrote this for debugging, exactly here lies my problem
for (int n = ml.getSize(); n > 1; n--) {
for (int i = 0; i < n - 1; i++) {
if (Employee.isSmaller(ml.get(i), ml.get(i + 1)) == false) {
Employee old = ml.set(i, ml.get(i + 1));
ml.set(i+1, old);
}
}
}
}
The "println" before my comment returns "0" in console... I am expecting "3" as this is the size I gave the "EmployeeList" as parameter of the constructor within my "EmployeeManagement" class. Where is my mistake ? And how can I access the size of the object I created in the "EmployeeManagement" class (the "3") ? I'm really looking forward to your answers!
Thanks,
Phreneticus
You are not storing size in your constructor. Something like,
public EmployeeList(int size) {
this.employeeArray = new Employee[size];
this.size = size; // <-- add this.
}
Also, setSize isn't going to automatically copy (and grow) the array. You will need to copy the array, because Java arrays have a fixed length. Finally, you don't really need size here since employeeArray has a length.
The size variable you are calling is the class field. If you take a quick look at your code, the getter is getting the field (which is initialized as zero when created). The size you are using it. The good way of doing it would be to get the size of the array in the getter like this:
public int getSize() {
return employeeArray.length;
}
This would return the size of the array in the object.
I'm currently working on a Bukkit plugin to claim custom areas, and I'm using rectangles (and .intersect()) to check if regions overlap before creating a claim.
I'm trying to figure a way where I don't need to check every single existing claim (of which there eventually will be tens of thousands) as surely this will take quite some time. I'll also need to check for claim owners when players do things such as break blocks or place blocks.
In my current system (which doesn't allow custom claim sizes, only squares) I only need to check at most about 10 claims because I can detect claims within the vicinity of the claim (at most 64 blocks away which is the max radius of claims in this system) but now the claim sizes can be infinitely large in theory with the new system.
Is checking all the rectangles going to take a massive amount of time? Am I being dumb, is there a way to check for rectangles within the vicinity even while the size is unlimited?
First of all checking thousands of rectangles is not gonna be a big deal for java(or your Plugin). Its simple math and should be done in millisecs. To deal with your owner Problem i would recommend you to create my own rectangle and owner class. So your rectangle can have a defined owner and you can simply check if the player is the owner of the area he is in right now.
public class custom_Area extends Rectangle{
private owner o;
public owner getOwner() {
return o;
}
public void setOwner(owner o) {
this.o = o;
}
}
EDIT:
I just tested it by creating 100.000 random rectangles and checking if one of them intersects with others.
--Custom rectangle class
public class area extends Rectangle{
private owner o;
public area(owner o, int i, int i1, int i2, int i3) {
super(i, i1, i2, i3);
this.o = o;
}
public owner getO() {
return o;
}
public void setO(owner o) {
this.o = o;
}
}
--Custom owner class
public class owner {
String name;
public owner(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
--Main class
public class Rectanglesearch {
public static area a[] = new area[100000];
public static owner o[] = new owner[10];
public static int intersectCounter = 0;
public static int ownerCounter = 0;
public static void main(String[] args) {
for(int y = 0; y<10;y++){
o[y] = new owner("y");
}
for (int i = 0; i < 100000; i++) {
a[i] = new area(o[(int)(Math.random() * 10)],random(),random(),random(),random());
}
checkArea(a[10]);
checkOwner(o[3]);
System.out.println("Area a[10] intersects with "+intersectCounter+" out of "+a.length);
System.out.println("Owner o[3] owns "+ownerCounter+" areas out of "+a.length);
}
public static int random(){
return (int)(Math.random() * 100000) + 1;
}
public static void checkArea(area ab){
for (area a1 : a) {
if (ab.intersects(a1)) {
intersectCounter +=1;
}
}
}
public static void checkOwner(owner ob){
for (area a1 : a){
if(a1.getOwner()==ob){
ownerCounter +=1;
}
}
}
}
method checkArea(area ab) returns you how man areas intersects with area ab
method checkOwner(owner ob) return you how man areas are owned my ob
Consider storing your rectangles in an acceleration structure such as a quadtree. To test a new rectangle against the existing set, you'd navigate down the tree to the node that would contain it, testing against the rectangles in each node along the way, but ignoring the rectangles in all the nodes you don't traverse. This quickly eliminates lots of rectangles that can't possibly intersect the new one, without having to test each one individually.
Other acceleration structures are also possible as alternatives, such as binary space partitioning. Read about spatial indexes for a list of several others that may be relevant.
Adding new rectangles to the set doesn't happen very often, so performance probably isn't a big concern. But I'd imagine that your plugin also needs to check whether a specific coordinate (such as a block) is within one of the claimed regions, and that may happen much more often — potentially every frame — so it really does need to be fast. A quadtree or other acceleration structure will be valuable for that.
I'm trying to take one parameter from the parent class of Car and add it to my array (carsParked), how can i do this?
Parent Class
public class Car
{
protected String regNo; //Car registration number
protected String owner; //Name of the owner
protected String carColor;
/** Creates a Car object
* #param rNo - registration number
* #param own - name of the owner
**/
public Car (String rNo, String own, String carColour)
{
regNo = rNo;
owner = own;
carColor = carColour;
}
/** #return The car registration number
**/
public String getRegNo()
{
return regNo;
}
/** #return A String representation of the car details
**/
public String getAsString()
{
return "Car: " + regNo + "\nColor: " + carColor;
}
public String getColor()
{
return carColor;
}
}
Child Class
public class Carpark extends Car
{
private String location; // Location of the Car Park
private int capacity; // Capacity of the Car Park - how many cars it can hold
private int carsIn; // Number of cars currently in the Car Park
private String[] carsParked;
/** Constructor for Carparks
* #param loc - the Location of the Carpark
* #param cap - the Capacity of the Carpark
*/
public Carpark (String locations, int room)
{
location = locations;
capacity = room;
}
/** Records entry of a car into the car park */
public void driveIn()
{
carsIn = carsIn + 1;
}
/** Records the departure of a car from the car park */
public void driveOut()
{
carsIn = carsIn - 1;
}
/** Returns a String representation of information about the carpark */
public String getAsString()
{
return location + "\nCapacity: " + capacity +
" Currently parked: " + carsIn +
"\n*************************\n";
}
}
Last Question Method
public String getCarsByColor (String carColour)
{
for (int num = 0; num < carsParked.length; num++)
{
if ( carColour.equals(carsParked[num]) )
{
System.out.print (carsParked[num]);
}
}
return carColour;
}
I have this so far so that if "red" is put in the parameters, it would list all the cars with the color red and it's corresponding information but does not seem to work ~_~.
You seem to have the wrong relationship here: a car park is not a car. I would recommend against using inheritance in either direction between these classes. And Carpark should probably just have an array or collection of cars.
Also note that the parameter carsIn isn't necessary - just get the length of the array of cars (or size() if it's a Collection).
Edit: Okay, ignoring the inheritance part, it seems like it makes sense to add cars when driveIn is called, and remove them when driveOut is called.
driveIn should probably take a Car as an argument, so the method can access the parameter you want to store (personally I would just store Car references, but fine). Since we're going to be adding and removing these parameters, it'll be much easier to use a List that can resize itself instead of an array, like ArrayList. For example:
private final List<String> carsRegNosParked = new ArrayList<String>();
public void driveIn(Car car) {
carsRegNosParked.add(car.getRegNo());
}
It's less clear what driveOut should do. It could take a specific registration number to remove:
public void driveOut(String regNo) {
carsRegNosParked.remove(regNo);
}
Or it could just indiscriminately remove a car, say the first car added:
public void driveOut() {
if (!carsRegNosParked.isEmpty()) {
carsRegNosParked.remove(0);
}
}
Note the difference between remove(Object) and remove(int).
First change carsParked to a list. So:
private String[] carsParked;
becomes
private List<String> carsParked;
Then in you constructor initialize it to an empty list by doing:
carsParked = new ArrayList();
Then in your drive in method, make it take a car parameter and pull the param you want:
public void driveIn(Car car) {
carsParked.add(car.getRegNo());
}
Also you do not need to keep track of the number of cars this way. Since you could always do carsParked.size() to find out.
Now I would probably change that list to be List<Car> instead of string and just dump the whole car in there. Sure you may only need one item right now, but who knows down the road, maybe you will need something else.
EDIT:
Sure you could do it with an simple array. The issue with that is sizing. Say you initially create an array of size 5, when you go to add the 6 item you will need to create a new larger array, copy the original data, then add the new item. Just more work. Now if the idea is you have a carpark, and it can have X number of spots then you initilize your array to that size from the begining.
public Carpark (String locations, int room){
location = locations;
capacity = room;
//this creates an array with the max number of spots
carsParked = new String[capacity];
//also good idea to init
carsIn = 0; //initial number of cars parked
}
then in your driveIn() method:
public void driveIn(Car car) {
carsParked[carsIn] =car.getRegNo();
carsIn=carsIn+1;
}
now driveOut()
public void driveOut(Car car) {
//loop through the array until we find the car
for (int i=0; i < carsParked.length; i=i+1){
if (car.getRegNo().equals(carsParked[i])){
//we found the car, so set the space null
carsParked[i] = null;
carsIn=carsIn-1;
//stop looping now
break;
}
}
}
Looks nice doesn't it. Well no it is not. Now the driveIn will not work, since we have null spots scattered all over the place. How do we fix it:
public void driveIn(Car car) {
//loop through the array until we find a null spot,
//then park the car
for (int i=0; i < carsParked.length; i=i+1){
if (carsParked[i] == null){
//we found the car, so set the space null
carsParked[i] = car.getRegNo();
carsIn=carsIn+1;
//stop looping now
break;
}
}
}
It could still be improved further. I would probably still change String[] carsParked to Car[] carsParked as to not throw away information.
I would also change the driveIn and driveOut methods to return booleans to indicate if the successfully parked or un-parked a car.
Final Edit:
Okay, if you want to keep track of what cars are parked in the car park and which spot they are in you need to know enough about each car to make it unique. In your case you may only need regNo. So when you call driveIn or driveOut you have to pass that information so we can store it at the appropriate index (parking spot) in the array. Otherwise all you will know is a car was parked somewhere, or that a car left. Not which spots are open.
So in short the parameter Car car in those two methods contain the information needed to uniquely identify each car that is being parked, or is leaving. Without it the car park instance would have no clue who is currently parked, or where they are parked.
This is a chunk of code I'm using for Google's antai challenge whenever I run it it seems to go into some endless loop then I get the stack trace at the bottom. I'm burnt out looking at this code I can't for the life of me figure this out.
public class Node
{
private final int xCoord, yCoord;
private int F, G, H;
private Tile location;
Node previousNode;
private Tile [] neighbors;
/*
G
the exact cost to reach this node from the starting node.
H
the estimated(heuristic) cost to reach the destination from here.
F = G + H
As the algorithm runs the F value of a node tells us how expensive we think it will be to reach our goal by way of that node.
*/
public Node(Tile loc)
{
location = loc;
xCoord = location.getCol();
yCoord = location.getRow();
F=G=H=0;
setNeighbors();
}
private void setNeighbors()
{
if(neighbors == null)
{
neighbors = new Tile[4];
}
neighbors[0] = new Tile(xCoord+1,yCoord);
neighbors[1] = new Tile(xCoord-1,yCoord);
neighbors[2] = new Tile(xCoord,yCoord+1);
neighbors[3] = new Tile(xCoord,yCoord-1);//error occurs here!!!!!!
}
}
/**
* Represents a tile of the game map.
*/
public class Tile implements Comparable<Tile> {
private final int row;
private final int col;
/**
* Creates new {#link Tile} object.
*
* #param row row index
* #param col column index
*/
public Tile(int row, int col) {
this.row = row;
this.col = col;
}
/**
* Returns row index.
*
* #return row index
*/
public int getRow() {
return row;
}
/**
* Returns column index.
*
* #return column index
*/
public int getCol() {
return col;
}
/**
* {#inheritDoc}
*/
#Override
public int compareTo(Tile o) {
return hashCode() - o.hashCode();
}
/**
* {#inheritDoc}
*/
#Override
public int hashCode() {
return row * Ants.MAX_MAP_SIZE + col;
}
/**
* {#inheritDoc}
*/
#Override
public boolean equals(Object o) {
boolean result = false;
if (o instanceof Tile) {
Tile tile = (Tile)o;
result = row == tile.row && col == tile.col;
}
return result;
}
/**
* {#inheritDoc}
*/
#Override
public String toString() {
return row + " " + col;
}
}
the actual error I'm receiving is:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at Node.setNeighbors(Node.java:37)
at Node.<init>(Node.java:25)
at AstarSearch.assessRoute(AstarSearch.java:73)
at MyBot.gatherFood(MyBot.java:153)
at MyBot.doTurn(MyBot.java:124)
at AbstractSystemInputParser.processLine(AbstractSystemInputParser.java:54)
at AbstractSystemInputReader.readSystemInput(AbstractSystemInputReader.java:18)
at MyBot.main(MyBot.java:25)
any help is appreciated
You need to do some debugging / clean up. From quick view I see, that in assesRoute() you
are never manipulating interesetedNode tile - this loop is not going to end normally.
It is also better to keep visited nodes in hash set - you only need to assure presence or absence, not a number of nodes. Alternative would be boolean flag in a node itself, this way you can work it with one list.
It seems like your creating more objects than your memory allows, guess your code is including an unfifite loop, you can make a static integer to count how many times the setNeighbors is called, its the routine where you create new objects, and show this integer on the catch statement of a try/catch around the main call of your class.
I don't know what this Google challenge is, so this may not be of much use (ie I don't know if you have access to the JVM), though it is a generic method to help diagnose this kind of problem.
I suggest turning on the JVM flag -XX:+HeapDumpOnOutOfMemoryError, and running your code again. An OutOfMemoryError will cause the heap to be dumped. You can then analyse this offline using something like Eclipse MAT.
The MyBot.doTurn() in the stack trace suggests your program is running over or discovering some kind of path... Are you sure this is a finite algorithm?
in assesRoute is a while loop. how many iterations do you expect? print out how many are actually done. if the difference is big, you know that there is a problem. take the start state of this iteration and try to understand why this state doesn't end the loop in proper time.
I am done with this assignment think god, and was wondering if someone could please check it so I can make sure there are no errors, it seems like I work hard on these programs but always doing something wrong. I am doing this course online so I have a hard time communicating with the instructor. I think my equals to methods might be wrong but, they seem to have no error when running the program and the program is 100% done. Please take the time to look over it, and thank you so much for your time.
Assignment:
About the first class
Create a class named RoomDimension that has two fields: one for the length of the room and another for the width. The RoomDimension class should have two constructors: one with no parameters (a default) and one with two parameters. The class should have all of the appropriate get and set methods, a method that returns the area of the room, a toString method that will allow us to print the length, width and area of the room and an equals method to compare room dimensions.
About the second class
Create another class named RoomCarpet that has two fields: one is a RoomDimension object and the other is a field that holds the cost of carpet per square foot. The class should have two constructors: one with no parameters and one with the two field parameters (RoomDimension and double). The class should have a get and set method for each field, a method that returns the total cost of carpeting the room, a toString method that will print all of the room information (length, width, area) and cost of the carpet per square foot and the total cost to carpet the room. (Dollar amounts should be displayed with two decimal places.), and an equals method that compares room dimensions and carpet cost.
About the application program
Write an application program that contains one RoomDimension object and one RoomCarpet object. The program should allow the user to enter the length and width of the room and the cost of the carpet per square foot. The program should instantiate both objects and use a simple System.out.println statement to print all of the information about the RoomCarpet object.
MY code:
import java.text.DecimalFormat;
public class RoomCarpet {
private RoomDimension rmSize;
private double pricePerSqFt;
//default constructor
public RoomCarpet()
{
this.rmSize = new RoomDimension();
this.pricePerSqFt = 0.00;
}
//parameters constructor
public RoomCarpet(RoomDimension rmSize, double pricePerSqFt)
{
this.rmSize = new RoomDimension(rmSize.getRmLength(),rmSize.getRmWidth());
this.pricePerSqFt = pricePerSqFt;
}
//accessor methods
public RoomDimension getRmSize()
{
return new RoomDimension(rmSize.getRmLength(),rmSize.getRmWidth());
}
public double getPricePerSqFt()
{
return this.pricePerSqFt;
}
// mutator methods
public void setRmSize(RoomDimension rmSize)
{
this.rmSize = new RoomDimension(rmSize.getRmLength(), rmSize.getRmWidth());
}
public void setPricePerSqFt(double pricePerSqFt)
{
this.pricePerSqFt = pricePerSqFt;
}
// Or price for the room to be carpeted
public double rmTotalCost()
{
return rmSize.getAreaRoom() * pricePerSqFt;
}
//toString method
public String toString()
{
DecimalFormat dollar = new DecimalFormat("$#,##0.00");
String str = this.rmSize.toString() + " Price per sq. ft : " +dollar.format(pricePerSqFt) + " Price to carpet Room: " + dollar.format(rmTotalCost()) + '\n';
return str;
}
public boolean equals(RoomCarpet object2)
{
boolean status;
if ((this.equals(object2)==true)&&(this.pricePerSqFt==object2.pricePerSqFt))
status = true;
else
status = false;
return status;
}
}
public class RoomDimension {
private int rmLength;
private int rmWidth;
//Default constructor
public RoomDimension()
{
rmLength=0;
rmLength=0;
}
// constructor with parameters
public RoomDimension(int rmLength, int rmWidth)
{
this.rmLength=rmLength;
this.rmWidth=rmWidth;
}
// accessor methods
public int getRmLength()
{
return this.rmLength;
}
public int getRmWidth()
{
return this.rmWidth;
}
//mutator methods
public void setRmLength(int rmLength)
{
this.rmLength=rmLength;
}
public void setRmWidth(int rmWidth)
{
this.rmWidth =rmWidth;
}
//area of the room
public int getAreaRoom()
{
return this.rmLength * this.rmWidth;
}
//toString Method
public String toString()
{
String str = "Room Length: " + this.rmLength + " Room Width: " + this.rmWidth + " Area of Room: " + this.getAreaRoom();
return str;
}
public boolean equals(RoomDimension object2)
{
boolean status;
if (this.getAreaRoom() == object2.getAreaRoom())
status = true;
else
status = false;
return status;
}
}
import java.util.Scanner;
public class CarpetPrice {
public static void main(String[] args)
{
RoomDimension rmSize;
RoomCarpet rmCarpet;
Scanner keyboard = new Scanner(System.in);
rmSize=new RoomDimension();
System.out.println(" Please enter the length of the room: ");
int rmLength= keyboard.nextInt();
rmSize.setRmLength(rmLength);
System.out.println("Please enter the rooms width: ");
int rmWidth = keyboard.nextInt();
rmSize.setRmWidth(rmWidth);
System.out.println("Please enter the price per sq foot: ");
double pricePerSqFt = keyboard.nextDouble();
rmCarpet = new RoomCarpet(rmSize, pricePerSqFt);
System.out.println("\n"+rmCarpet.toString());
}
}
The equals method must have an Object argument and you have to override the hashCode method too.
#Override
public boolean equals(Object obj)
{
}
I would say that for RoomDimension, two objects are equal only if both length and width match. Especially if you're laying carpet, a 4x5 room would be much different from a 1x20 hallway, even though the total area is the same. For the RoomCarpet object, again equal only if both the dimensions are equal and the price is the same, I guess.
Also, I would write some tests because you may be surprised at what happens when you call RoomCarpet's .equals() method (as written above).
Finally, pay attention to your indenting because that's important for any reader of your code.