0

I am writing a code to measure the surface area of a box and volume of the box. Finally, I got it to works. Now the challenges are I have to make 4 object and and store it into array and then use enhanced for loop to go through each box in the array. I mean when you loop through the array, it will get to first box, and ask you to enter the length, width, and height. Then it will show you the first box's length, width, height, surface area, and volume. I try to find an example for it but I cant find anything. I am still trying to make it work. Thank you for your help. here is my Box code.

public class Box
{
    private double length = 1.0;
    private double width = 1.0;
    private double height = 1.0;

    //constructor
    public Box (double l, double w, double h)
    {
        setLength(l);
        setWidth(w);
        setHeight(h);
    }

    //set length method
    public void setLength(double l)
    {
        if(l > 0)
        {
            length = l;
        }
        else
        {
            length = 1.0;
        }
    }

    //set width method
    public void setWidth(double w)
    {
        if(w > 0)
        {
            width = w;
        }
        else
        {
            width = 1.0;
        }
    }

    //set height method
    public void setHeight(double h)
    {
        if(h > 0)
        {
            height = h;
        }
        else
        {
            height = 1.0;
        }
    }

    //calculate area method
    public double calculateArea(double length, double width)
    {
        return (length*width);
    }

    //calculate volume method
    public double calculateVolume(double length, double width, double height)
    {
        return (length*width*height);
    }

    //get length method
    public String getLength()
    {
        return String.format("%f", length);
    }

    //get width method
    public String getWidth()
    {
        return String.format("%f",width);
    }

    //get height
    public String getHeight()
    {
        return String.format("%f",height);
    }   

    public String toString()
    {
        return String.format("Length is %s.\nWidth is %s.\nHeight is %s.\n", getLength(), getWidth(), getHeight());
    }

}

and here is my main code

import java.util.Scanner;

public class BoxTest
{
    public static void main(String[] args)
    {
        //Box boxOne, boxTwo, boxThree, boxFour;          
        double l;
        double w;
        double h;

        Scanner input = new Scanner(System.in);
        int[] boxes = new int[4];
        System.out.print ("Enter the length of your box:");
        l= input.nextDouble();
        System.out.print ("Enter the width of your box:");
        w= input.nextDouble();
        System.out.print ("Enter the height of your box:");
        h= input.nextDouble();

        Box boxOne = new Box(l, w, h);
        System.out.println(boxOne.toString());
        System.out.printf("The surface area of the box is %f.\nThe volume of the box is %f.\n", 
                          boxOne.calculateArea(l, w), boxOne.calculateVolume(l, w, h));


    }
}
NumbNuts
  • 81
  • 1
  • 3
  • 9

4 Answers4

0

You haven't declared those doubles in your constructor.

it should be like this:

double l = 50.55;
double w = 40.99;
double h = 12.33;
Box boxOne = new Box(l, w, h);
...

EDIT:

I just saw that you are trying to get the values from the Scanner.

You should first read them, store them in the variables, and then create a new instance of Box. Not the other way around.

So,

Scanner input = new Scanner(System.in);
System.out.print ("Enter the dimension of your box:");
l= input.nextDouble();
w= input.nextDouble();
h= input.nextDouble();

Box boxOne = new Box(l, w, h);
...
Luis Lavieri
  • 3,689
  • 5
  • 32
  • 60
  • If you want to be technical about it, your `Box` object should not be allowed to mutate once created (a real-world box doesn't change dimensions once created). Therefore, your objects should be immutable (no setter methods and parameters should be `final`) – hfontanez Dec 18 '20 at 18:15
0

Because you do not use semicolons to separate parameters, use commands instead.

Also if you're passing a parameter you don't need to specific the type.

Try using Box boxOne = new Box(length, width, height);

Konato_K
  • 73
  • 1
  • 1
  • 8
  • I treid this method before, and I got 4 errors. one of the errors say **"error: ')' expected. Box boxOne = new Box(length; width; height);"** with arrpw pointing at "l" length, "w" width, "h" height. Another error is **""error: ';' expected. Box boxOne = new Box(length; width; height);""** with arrow pointing at ")" – NumbNuts Dec 05 '14 at 23:43
  • @NumbNuts because width, length and height do not exist in your main function, the ones you declare in your Box class can't be used from the main (and if you want to use those values always then don't pass parameters to the constructor) You're declaring 3 variables with those names in your name AFTER you use them, you need to declare them before AND INITIALIZE THEM, if you don't set their values you can't use them Alternative I think something like `Box boxOne = new Box(1.0, 1.0, 1.0);` would be cleaner – Konato_K Dec 05 '14 at 23:49
  • Sorry, I get even more confused. Well, I should've post my complete requirements for the code. Let me just re-edit my problem. The reason why I don't want to edit my complete problem is I am not even half way done with my main code, because I got confused on how to set 4 objects of box into array, can go through each of them and find the length, width, height, area, and volume. – NumbNuts Dec 05 '14 at 23:57
0

See changes and comments in the code:

public class Box
{
    private double length;  // No need to set default values here
    private double width;   // No need to set default values here
    private double height;  // No need to set default values here

    //alternative constructor
    public Box()
    {
        //Just instantiate the box, but do not set anything.
    }

    //constructor
    public Box (double l, double w, double h)
    {
        this.length = l;  // Don't use method calls that can be overridden in
        this.width = w;   // your constructor.
        this.height = h;
    }

    //set length method
    public void setLength(double l)
    {
        if(l > 0)
        {
            this.length = l; // You have to use this.length to set
                             // the value stored in the object
        }
        else
        {
            this.length = 1.0;
        }
    }

    //set width method
    public void setWidth(double w)
    {
        if(w > 0)
        {
            width = w; // same as above
        }
        else
        {
            width = 1.0; // same as above
        }
    }

    //set height method
    public void setHeight(double h)
    {
        if(h > 0)
        {
            height = h; // same as above
        }
        else
        {
            height = 1.0; // same as above
        }
    }

    //calculate area method
    public double calculateArea() // don't use new parameters. Instead use the values
                                  // stored in the object (this.length and this.width)
    {
        return (this.length * this.width);
        // the formula is not correct, because this only calculates the area
        // of one side of the box, but I will let you figure that out yourself ;-)
    }

    //calculate volume method
    public double calculateVolume() // same as above
    {
        return (this.length * this.width * this.height);
    }

    //get length method
    public String getLength()
    {
        // It's not advisable to convert the type of the variable
        // in a standard getter, you should rather use something like
        // getLengthAsString and use getLength to return the length as
        // it is.

        return String.format("%f", this.length); // You have to use this.length to return
                                                 // the value stored in the object
    }

    //get width method
    public String getWidth()
    {
        return String.format("%f",width); //same as above
    }

    //get height
    public String getHeight()
    {
        return String.format("%f",height); //same as above
    }   

    public String toString()
    {
        return String.format("Length is %s.\nWidth is %s.\nHeight is %s.\n", getLength(), getWidth(), getHeight());
    }

For the main function:

To declare an array of 4 boxes you would do:

Box[] boxes = new Box[4];

And to put a box at the first position in the array:

boxes[0] = new Box();

then read the user input and set the box-properties accordingly:

    newBox.setHeight(scanner.nextDouble());
    newBox.setLength(scanner.nextDouble());
    newBox.setWidth(scanner.nextDouble());

This should give you all you need to fix the problem.

Chris
  • 478
  • 4
  • 16
  • thank you, I just re-edit my problem because seems too many answer that seems doesn't comply to the requirement. I apologize for that. – NumbNuts Dec 06 '14 at 00:30
  • The task you are describing is not quite clear to me, because IMHO it does not make sense to declare an array of boxes, with 4 boxes in it and then afterwards go through the boxes and set the attributes. Sounds like the typical school question with no practical relevance ;-) Anyway - I'll try and edit my answer. – Chris Dec 06 '14 at 07:44
  • Another thing as a comment: People here are often very unhappy with beginners questions, and you might not get answers. Try a forum like http://www.coderanch.com for beginners questions. – Chris Dec 06 '14 at 09:13
0

My recommendation is to break the problem into sub-problems and create a solution for each. This is called Problem Decomposition. Once all of the solutions are created, integrate them. In theory, integrating all of the solutions together should solve the entire problem. In your case, I think this a good, logical way to decompose your problem:

  1. Box creation (Setting dimension on each Box)
  2. Storing the boxes
  3. Calculating Volume
  4. Calculating Surface Area
  5. Capturing user input
  6. Iterating through Box collection

Box Creation

My recommendation is that, since all these subproblems are all related to your Box object, create helper classes and/or methods to handle each one. In this case, you can create a method that given height, width, and length, returns a new instance of Box.

public static Box createBox (int height, int width, int length) {
    return new Box(height, width, length);
}

In turn, your Box class should be storing these parameters as global members:

public class Box {
    private final int height, width, length;
    public Box (int height, int width, int length) {
        this.height = height;
        ...
    }
    ... (other methods omitted)
}

I know this looks like overkill, and I agree. BUT, what this does is teach you a very valuable lesson in Single Responsibility Principle as well as code modularization which helps testing these smaller jobs independently. I am a strong believer that, helper classes should contain nothing but static methods. Why? Because it doesn't make much sense to create instances of objects that never hold data. In Java, Math class is an example of what I am talking about.

Alternatively, you could create boxes without dimension and set the height, width, and length separately, but I don't believe this is a good way to go about it. For example, if one or more parameters are not set, you could end up with erroneous behavior. Lastly, your Box class should create immutable objects so that dimensions cannot be changed once an instance of the class is created. I will address this point last.

Storing the boxes

If this is a single-class project, maybe you want to make this collection (most likely a java.util.List type) a global attribute of your class. If this project contains more than one class, the class that calls your createBox method will have some code to add the return value of this method into some list. Something like this should do:

Box box1 = BoxUtils.createBox(1, 2, 3);
myList.add(box1);
Box box2 = BoxUtils.createBox(4, 5, 6);
myList.add(box2);
...

You get the idea. That said, this should be better done in a loop. We will get back to this later. For now, just remember this is NOT done by the box utilities or helper class. This is done by the class that calls it; in your case, BoxTest

public class BoxTest {
    public static void main(String[] args) {
        // TODO get user input
        // create box
        // add box to list
        ...
}

Calculate Volume

This method should be in Box class...

box.getVolume();

Since the parameters are passed via the constructor, you don't need to pass them to this method again. However, you could argue that since you have a utilities class for all box related helper methods, you could move this responsibility there and have the Box class to be a simple POJO (that does not how to calculate its own volume or area). I prefer this approach. If you decide to do this, you need to pass a Box instance to the helper method and return the result.

Box box = new Box(1, 2, 3);
int volume = BoxUtils.calculateVolume(box); // preferred

Calculate Surface Area

This method should also be in Box class or box utilities...

int area = box.getSurfaceArea(); // In Box, or
int area = BoxUtils.getSurfaceArea(box); // in BoxUtils (preferred)

Capturing User Input

Iterating through the collection of boxes was left for last for a reason. I think you should firs try to get your problem working with a single box first. Make sure you open and close your Scanner object properly, get the user input correctly, etc. Then, once you test your solution to your satisfaction, expand your solution to capture inputs and create boxes in a loop operation. That way if it fails, you know your problem is isolated to this one part of the problem and not something else. For situations like this is why Problem Decomposition is crucial.

Your original problem uses double for your height, width, and length. I am using int for simplicity.

public static void main(String[] args) {
    
    Scanner input = new Scanner(System.in);
    System.out.println("Enter height, width, and length for the box (space-separated i.e. 10 20 30)");
    int height = input.nextInt();
    int width = input.nextInt();
    int length = input.nextInt();
    input.close();

    Box box = new Box(height, width, length);
    System.out.println(box); // I overrode Object#toString() in Box class to do this.
}

My output

Enter height, width, and length for the box (space-separated i.e. 10 20 30)
10 20 30
height: 10; width: 20; length: 30

Iterating Through Box Collection

You mentioned that you wanted to use enhanced for loop for this. You probably won't be able to do this for what I am recommending. See this article for details. Instead, a traditional for loop will do just fine. Since I know everything has worked so far, I can now modify my existing solution to introduce looping to capture the user inputs

public static void main(String[] args) {
    Box[] boxArray = new Box[4];
    Scanner input = new Scanner(System.in);
    for (int i = 0; i < boxArray.length; i++) {
        System.out.println("\nEnter height, width, and length for the box (space-separated i.e. 10 20 30)");
        int height = input.nextInt();
        int width = input.nextInt();
        int length = input.nextInt();
        Box box = new Box(height, width, length);
        System.out.println(box);
    // TODO print volume and area   
    }
    input.close();
}

Notice that the code is basically the same. I just created an array to store the boxes and a loop to repeat capturing the user's input until the array is full (4 boxes). You could modify this loop to go on forever and only break after a special character is pressed (which is out of scope for what you need to do).

Once I get this part done, it is time to add printing out (calculate) the volume and area for each box. You can do this inside the same loop (recommended) or create another loop and iterate through the array to display these results.

Now, to finish, I just replaced the TODO with the following code:

System.out.println("Box " + (i+1) + " surface area: " + BoxUtils.calculateSurfaceArea(box));
System.out.println("Box " + (i+1) + " volume: " + BoxUtils.calculateVolume(box));

Now when I execute the code, I will get an output that resembles the following:

Enter height, width, and length for the box (space-separated i.e. 10 20 30)
1 2 3
Box 1 surface area: 22.0
Box 1 volume: 6.0

Coding for Immutability

Coding for immutability is out of scope for your requirement, but I think it is important to mention. Immutability has many benefits, one of which is thread safety. It is obviously not without drawbacks, but in my opinion the benefits outweighs them. For this example, I just made the fields of the Box class private and final, and I did not provide setter methods. So, your Box class should look like this:

public class Box {

    private final int height, width, length;

    public Box(int height, int width, int length) {
        this.height = height;
        this.width = width;
        this.length = length;
    }

    public int getHeight() {
        return height;
    }

    public int getWidth() {
        return width;
    }

    public int getLength() {
        return length;
    }
    
    @Override
    public String toString() {
        return "height: " + height + "; " + "width: " + width + "; " + "length: " + length;
    }
}

Your BoxUtils like this:

public class BoxUtils {

    private BoxUtils() {
        throw new AssertionError("BoxUtils cannot be instantiated");
    }

    public static Box createBox (int height, int width, int length) {
        return new Box(height, width, length);
    }
    
    public static double calculateVolume(Box box) {
        return box.getWidth() * box.getHeight() * box.getLength();
    }
    
    public static double calculateSurfaceArea(Box box) {
        int width = box.getWidth();
        int height = box.getHeight();
        int length = box.getLength();
        return 2 * ((width * length) + (height * length) + (height * width));
    }
}

and finally your BoxTest like this:

public class BoxTest {

    public static void main(String[] args) {
        Box[] boxArray = new Box[4];
        Scanner input = new Scanner(System.in);
        for (int i = 0; i < boxArray.length; i++) {
            System.out.println("\nEnter height, width, and depth for the box (space-separated i.e. 10 20 30)");
            int height = input.nextInt();
            int width = input.nextInt();
            int depth = input.nextInt();
            Box box = new Box(height, width, depth);
            System.out.println("Box " + (i+1) + " surface area: " + BoxUtils.calculateSurfaceArea(box));
            System.out.println("Box " + (i+1) + " volume: " + BoxUtils.calculateVolume(box));
        }
        input.close();
    }
}
hfontanez
  • 2,640
  • 2
  • 21
  • 29