Math from class isn't carrying in to object

I have to make a program that has the Circle class which calculates the area and circumference of a circle by accepting a parameter for r from a new circle object in main. I fed it the radius value of 14. This is what it should output:

***** Circle *****
radius         14.0
area           615.75164
circumference  87.96452

But instead I'm getting this

***** Circle *****
radius          14.0
area            0.0
circumference   0.0

Why is this happening and how can I fix it? I was given the overall shell of the code to make work in java and I have to keep it for the most part how it was presented to me, so while I appreciate the intention of giving recommendations on better ways to structure things and make this program in general, the teacher wants me to do it this way. The only thing I'm not sure of is what to do with setRadius(), and whether or not I should have declared r at the top of the class.

package shapedemo;

class Circle {
    private double radius;
    private double circumference;
    private double area;
    private double r;

// constructors
    public Circle(){
        radius = 1;
    }
    public Circle(double r) {
        radius = r;
    }

// setters and getters
    public void setRadius(double radius){
        this.radius = radius;
    }
    public double getRadius(){
        return radius;
    }

// other methods
    public double calcArea() {
        area = Math.PI * r * r;
        return area;
    }
    public double calcCircumference(){
        circumference = Math.PI * 2 * r;
        return circumference;
    }

// display method
    public void display() {
/*blank line
***** Circle *****
radius      nnnn.nn
area        nnnn.nn
circumference   nnnn.nn
blank line
*/
        System.out.println("\n***** Circle *****\nradius    " + radius + "\narea        " + area + "\ncircumference " + circumference + "\n");
    }
}

public class ShapeDemo {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        Circle circle1 = new Circle(14);
        circle1.display();
    }

}
Jon Skeet
people
quotationmark

Your area and circumference variables are only being set if you call the appropriate calculation methods (calcArea and calcCircumference). You're not calling them, so they have the default values of 0.

You could fix this in your main method:

public static void main(String[] args) {
    Circle circle = new Circle(14);
    circle.calcArea();
    circle.calcCircumference();
    circle.display();
}

... although you'd also have to fix your methods to use radius instead of r, as you're never setting r.

Personally I think it would be better to either move the logic into your constructor or calculate it on demand with methods rather than having fields at all for them.

First approach, in the constructor:

final class Circle {
    private final double radius;
    private final double circumference;
    private final double area;

    public Circle() {
        this(1); // Delegate to other constructor
    }

    public Circle(double r) {
        radius = r;
        area = Math.PI * radius * radius;
        circumference = Math.PI * 2 * radius;
    }

    public void display() {
        System.out.println(
            "\n***** Circle *****" +
            "\nradius    " + radius + 
            "\narea        " + area + 
            "\ncircumference " + circumference + "\n");
    }
}

Second approach, making methods compute the values:

final class Circle {
    private final double radius;

    public Circle() {
        this(1); // Delegate to other constructor
    }

    public Circle(double r) {
        radius = r;
    }

    public double getRadius() {
        return radius;
    }

    public double getArea() {
        return Math.PI * radius * radius;
    }

    public double getCircumference() {
        return Math.PI * 2 * radius;
    }

    public void display() {
        System.out.println(
            "\n***** Circle *****" +
            "\nradius    " + radius + 
            "\narea        " + getArea() + 
            "\ncircumference " + getCircumference() + "\n");
    }
}

In both cases, I've made this an immutable type - while you can keep it mutable, in the first case that would mean recomputing the area and circumference. In that case you'd probably want your constructor to just call setRadius() and make that method do all the computations.

For example:

final class Circle {
    private double radius;
    private double circumference;
    private double area;

    public Circle() {
        this(1); // Delegate to other constructor
    }

    public Circle(double r) {
        setRadius(r);
    }

    public void setRadius(double r) {
        radius = r;
        area = Math.PI * radius * radius;
        circumference = Math.PI * 2 * radius;
    }

    public double getRadius() {
        return radius;
    }

    public double getArea() {
        return area;
    }

    public double getCircumference() {
        return circumference;
    }

    public void display() {
        System.out.println(
            "\n***** Circle *****" +
            "\nradius    " + radius + 
            "\narea        " + area + 
            "\ncircumference " + circumference + "\n");
    }
}

people

See more on this question at Stackoverflow