1

I'm trying to figure this out but I can't seem to get it to compare correctly.

As I try to setup the code whenever I run it the result would end up becoming True when I need it to produce a false test as well. Extensive testing shows it to be always true and I have no idea how to produce a false on it.

import java.util.Scanner;

public class LandTract
{
    // instance variables
    private static double length , width, area;

    /**
     * Constructor for objects of class LandTract
     */
    public LandTract(double length, double width, double area)
    {
        // initialise instance variables
        length = 0;
        width = 0;
    }

    public LandTract(double length, double width)
    {
        this.length = length;
        this.width = width;
    }
    
    public void setLength(double length)
    {
        this.length = length;
    }
    
    public double getLength()
    {
        return length;
    }
    
    public void setWidth(double width)
    {
        this.width = width;
    }
    
    public double getWidth()
    {
        return width;
    }
    
    public double getArea()
    {
        return area = length * width;
    }
    
    public String toString()
    {
        String str = "Length: " + length + "\nWidth: " + width;
        return str;
    }
    
    public boolean equals(Object obj)
    {
        LandTract land = (LandTract) obj;
        if (this.length != land.length)
            return false;
        if (this.width != land.width)
            return false;
        if (this.area != land.area)
            return false;
        
            return true;
    }
    
    public static void main(String[] args)
    {
        Scanner key = new Scanner(System.in);
        
        System.out.print("Enter the length of the first tract of land: ");
        length = key.nextDouble();
        key.nextLine();
        System.out.print("Enter the width of the first tract of land: ");
        width = key.nextDouble();
        key.nextLine();
        LandTract land1 = new LandTract(length , width);
        System.out.println("The area of the first tract of land is " + land1.getArea());
        System.out.println();
        
        System.out.print("Enter the length of the second tract of land: ");
        length = key.nextDouble();
        key.nextLine();
        System.out.print("Enter the width of the second tract of land: ");
        width = key.nextDouble();
        key.nextLine();
        LandTract land2 = new LandTract(length, width);
        System.out.println("The area of the second tract of land is " + land2.getArea());
        System.out.println();
        
        if (land1.equals(land2))
            System.out.println("Both tracts of land are the same size.");
        else
            System.out.println("They are different sizes.");
    }
}
GSerg
  • 76,472
  • 17
  • 159
  • 346
  • Please show what values you're using in your tests. A unit test would be better than user-driven tests, for the sake of repeatability. Also, nothing seems to be setting your `area` field, but it is included in your equality test. – Bill the Lizard Feb 23 '21 at 20:28
  • add @Override just to make sure – Bruno CL Feb 23 '21 at 20:35
  • `static` means "shared among all LandTracts/objects" ...you set class variables through "instance accessors" (getter/setter), thus the confusion. Remove `static`from the variable declaration ..and use "local variables" (if at all) in the main method! ;) – xerx593 Feb 23 '21 at 20:42
  • Thank you everyone for helping me I was able to figure it thanks to you guys' help. – Timothy Nguyen Feb 23 '21 at 21:19

2 Answers2

0

The best example for a confusing & ironically erroneous comment:

// instance variables
private static double length , width, area;

The program works much better, when you:

  1. (Really) Introduce instance variables:

    private double length , width, area;
    
  2. Fix compiler problems in main method (by declaring local variables with the same identifier ..no good style but quick):

    public static void main(String[] args) {
       double length, width;
       // ...
    }
    
xerx593
  • 12,237
  • 5
  • 33
  • 64
  • So the main issue was it because I was overly complicating it? Thank you very much as well it helped it work – Timothy Nguyen Feb 23 '21 at 21:17
  • I am not sure how you got there. Probably re-using variable names (length, width) and avoiding compiler errors ("make static"). But (I hope) you learned (the "hard" way): The *difference between "instance" and "static"* (non-instance/class ...variables etc.;) Welcome, bud! – xerx593 Feb 23 '21 at 21:47
  • a simple but good question (for deeper research & studies): https://stackoverflow.com/q/1215881/592355 – xerx593 Feb 23 '21 at 21:50
0

The problem here is that the values being compared (length, width, and area) are static fields, not instance fields. This means that any reference to them will use the same global value, regardless of which instance of the class is referencing them.

Of particular relevance, this.length != land.length in the equals method will always return true, since both this.length and land.length will refer to the same value. (Note that this guarantee is no longer true if multiple threads are involved, but that's not the case with this example.)

This also means that any call to a constructor or a setter will set the shared static fields, overwriting the value previously written when calling a setter or constructor on another instance. For instance, the length, width constructor will overwrite the static length & width fields, and the setLength method will overwrite the static length field.

public LandTract(double length, double width)
{
    this.length = length;
    this.width = width;
}

public void setLength(double length)
{
    this.length = length;
}

The fix is to change these fields to instance fields, rather than static ones:

public class LandTract
{
    private double length, width, area;

    // [...]
}
M. Justin
  • 14,487
  • 7
  • 91
  • 130