Null-Pointer Exception Error at toString - java

The null-pointer exception error occurs in my toString method. I'm at a loss as to why. The error can occur through multiple ways. Most commonly, an object's reference is declared but the object itself remains uncreated. I've declared and created (is initialized the right word?) Mycircle circle1 = new Mycircle (); and Mypoint center = new Mypoint ();
I suspected that I hadn't initialized any of my fields when I invoked my getter methods, but that's not true. The setter methods work cleanly -- I've been successful in inputting values. Doesn't that imply that my getter methods can access some non-null value.
import java.util.Scanner;
public class MyCircle {
private Mypoint center;
private double radius;
Scanner input = new Scanner (System.in);
public MyCircle() {
radius = 0.0;
Mypoint center = new Mypoint ();
System.out.println("Enter coordinates here");
center.setCoordinateX(input.nextDouble());
center.setCoordinateY(input.nextDouble());
}
public String toString(MyCircle object) {
return "Circle # " + "(" + object.center.getCoordinateX() + "," +
object.center.getCoordinateY() + ")" + ". Its radius is " +
object.radius;
}
public double calcArea(MyCircle object) {
double area = Math.pow(object.radius, 2) * Math.PI;
return area;
}
public static void main (String[]args) {
MyCircle circle1 = new MyCircle ();
circle1.radius = 3.0;
System.out.println(circle1.calcArea(circle1));
System.out.println(circle1.toString(circle1));
}
}
class Mypoint {
private double posX;
private double posY;
public void setCoordinateX(double x) {
posX = x;
}
public void setCoordinateY(double y) {
posY = y;
}
public double getCoordinateX() {
return posX;
}
public double getCoordinateY() {
return posY;
}
}

In your MyCircle constructor, you're creating a local variable called center here:
Mypoint center = new Mypoint ();
What you probably want is to initialize the instance member:
center = new Mypoint ();

Your code doesn't make much sense, presumably this
public String toString(MyCircle object)
{
return "Circle # " + "(" + object.center.getCoordinateX() + ","
+ object.center.getCoordinateY() + ")"
+ ". Its radius is " + object.radius;
}
Should be
#Override
public String toString() {
return "Circle # (" + center.getCoordinateX() + ","
+ center.getCoordinateY()
+ "). Its radius is " + radius;
}
Then let's fix your constructor, use this so you know you're updating the instance field (instead of shadowing it) -
public MyCircle() {
this.radius = 0.0;
this.center = new Mypoint(); // <-- this.center
System.out.println("Enter coordinates here");
this.center.setCoordinateX(input.nextDouble());
this.center.setCoordinateY(input.nextDouble());
}

First of all, your toString() method is untypical. You want a Circle#toString() with no argument and produce a print representaton of yourself (i.e. this instead of object=).
Your toString method can fail if:
object is null
object.center is null
object.center.getCoordinateX() or getCoordinateY() itself throws exception.
The later case would be visible in the stacktrace, the other two cases all show the same line number as the cause.
It looks like the second case is your problem (as you fill a local variable and not the field of MyCircle).
BTW: using a input scanner in a constructor is a horrible layering violation. You should seperate input/output/user interaction logic from the geometric (circly, point) classes.

There are many things wrong in your code beside what #Mike pointed out.
Getting input from the user within the constructor is bad. You should get the input in the main method, and pass it to the constructor. In addition, you don't initialize the radius. It remains 0.0.
The constructor call should look like this (the MyPoint object passed to the constructor should be initialized prior to calling the constructor) :
MyCircle circle1 = new MyCircle (center, radius);
The constructor should look like this :
public MyCircle(MyPoint center, double radius)
{
this.radius = 0.0;
this.center = center;
}
The toString and calcArea methods don't need a parameter. They should operate on the current object (this) :
public String toString()
{
return "Circle # " + "(" + this.center.getCoordinateX() + "," + this.center.getCoordinateY() + ")" + ". Its radius is " + this.radius;
}

Related

How to fix "Cannot invoke "java.awt.Point.getX()" because "this.p" is null"

For an inheritance practice assignment, I have a class Square which extends rectangle, and here are the relevant methods:
public class Square extends Rectangle {
private Point p;
private int sideLength;
public Square(Point p, int sideLength){
super(p);
this.sideLength = sideLength;
}
public String toString(){
return getClass().getName() + "\nCenter point: (" + p.getX() + ',' + p.getY() + ") \nSide Length: " + sideLength + " \nArea: " + this.getArea() + " \nPerimeter: " + this.getPerimeter();
}
}
there's also a getArea() and getPerimeter() method but neither of those are causing this issue.
I have a separate class to test this one:
public class SquareTest {
public static void main(String[] args){
ArrayList<Square> squareList = new ArrayList<>();
Point p1 = new Point(1, 1);
Point p2 = new Point(1, 2);
Point p3 = new Point(4, 1);
Point p4 = new Point(2, 3);
Point p5 = new Point(5, 4);
Square one = new Square(p1, 1);
Square two = new Square(p2, 2);
Square three = new Square(p3, 4);
Square four = new Square(p4, 4);
Square five = new Square(p5,5);
squareList.add(one);
squareList.add(two);
squareList.add(three);
squareList.add(four);
squareList.add(five);
for (Square each : squareList){
System.out.println(each.toString());
System.out.println();
}
}
}
What it's supposed to do is print out the toString() result for each of the five square objects, where one square looks like this:
Square
Center point: (1,1)
Side Length: 1
Area: 1
Perimeter: 1
but instead i get the following runtime error:
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "java.awt.Point.getX()" because "this.p" is null
at Square.toString(Square.java:21)
at SquareTest.main(SquareTest.java:23)
I'm confused as to why it thinks this.p is null when I've clearly instantiated five Point objects. Any ideas?
NullPointerException was caused because you haven't initialized the p in Square class. Yu have just passed it to the Rectangle constructor so it is the p in Rectangle class which is getting initialized.
Since you are not using the point object in your Square rather than just passing it to the super class, there is no need to declare a Point object in the Square class. If your Rectangle class has a getter method for Point p then, you could use that in the Square class.
Assuming that Rectangle class has a getter method for p, You could refactor your Square class to :
public class Square extends Rectangle {
private int sideLength;
public Square(Point p, int sideLength){
super(p);
this.sideLength = sideLength;
}
public String toString(){
return getClass().getName()
+ "\nCenter point: (" + getP().getX() + ',' + getP().getY()
+ ") \nSide Length: " + sideLength
+ " \nArea: " + this.getArea()
+ " \nPerimeter: " + this.getPerimeter();
}
}

Problems with toString() and Overriding Methods

I am having a problem with this code. It is not calculating area correctly. I need it to calculate the cross-sectional area of a Cylinder/Piston and the surface area of the cylinder. If you notice the output it seems that both values are the same values for when I use the getArea() method. Java is getter confused as to what getArea() to use? strong text I am trying to over-ride the getArea() [Surface Area] with getArea() [cross -sectional area] but it is not working?
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.println(
"\n\nInput the radius, then the height, then if the cylinder is filled (input 1 if it is filled and input 0 if not, and then enter the color");
double radius = scan.nextDouble();
double height = scan.nextDouble();
int filled = scan.nextInt();
boolean isFilled;
if (filled == 1) {
isFilled = true;
} else {
isFilled = false;
}
String c = scan.nextLine();
String x = scan.nextLine();
Cylinder cyl = new Cylinder(radius, height, isFilled, x);
System.out.println("\n\n This is a Cylinder and its properties");
System.out.println(cyl);
Piston small= new Piston();
System.out.println ("\n\n This is small Piston");
System.out.println(small);
Piston big = new Piston(55.6, 1234.4, true, "red", 1200, 12.3);
System.out.println ("\n\n This is big Piston");
System.out.println(big);
}
}
class Shape {
private String color = "yellow";
private boolean filled;
public Shape() {
}
public Shape(String color, boolean filled) {
this.color = color;
this.filled = filled;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public boolean isFilled() {
return filled;
}
public void setFilled(boolean filled) {
this.filled = filled;
}
public String toString() {
return "\nThe color is : " + color + " and shape fill is : " + filled;
}
}
class Cylinder extends Shape {
private double cylinderRadius;
private double cylinderHieght;
public Cylinder() {
cylinderHieght = 10;
cylinderRadius = 2.5;
}
public Cylinder(double height, double radius) {
cylinderRadius = radius;
cylinderHieght = height;
}
public Cylinder(double height, double radius, boolean filled, String color) {
super(color, filled);
cylinderRadius = radius;
cylinderHieght = height;
}
public double getRadius() {
return cylinderRadius;
}
public double getHieght() {
return cylinderHieght;
}
public double getArea() {
double p = 3.14;
return 2 * p * cylinderRadius * cylinderRadius + 2 * p * cylinderRadius * cylinderHieght;
}
public double getVolume() {
double p = 3.14;
return p * cylinderRadius * cylinderRadius * cylinderHieght;
}
#Override
public String toString() {
return super.toString() + " \nRadius= " + cylinderRadius + " Height= " + cylinderHieght
+ " Cylinder total surface Area= " + getArea() + " volume= " + this.getVolume() + ".";
}
}
class Piston extends Cylinder{
private double shaftLength;
private double myPressure;
public Piston(){
shaftLength=1;
myPressure=1;
}
public Piston(double height, double radius, boolean filled, String color, double length, double pressure){
super(height, radius, filled, color);
shaftLength=length;
myPressure=pressure;
}
public double getShaftLength(){
return shaftLength;
}
public double getPressure(){
return myPressure;
}
#Override
public double getArea(){
return getRadius()*getRadius()*3.14;
}
public double getVolume(){
return super.getVolume();
}
#Override
public String toString(){
return super.toString()+"\n the cross sectional area of Piston = "+this.getArea()+" shaftlength="+shaftLength+" pressure="+myPressure+" .";
}
}
Here is the output if I put in a radius of 5 and a height of 10.
Input the radius, then the height, then if the cylinder is filled
(input 1 if it is filled and input 0 if not, and then enter the color
5 10 1 Blue
This is a Cylinder and its properties
The color is : Blue and shape fill is : true Radius= 10.0 Height= 5.0
Cylinder total surface Area= 942.0 volume= 1570.0.
This is small Piston
The color is : yellow and shape fill is : false Radius= 2.5 Height=
10.0 Cylinder total surface Area= 19.625 volume= 196.25. the cross sectional area of Piston = 19.625 shaftlength=1.0 pressure=1.0 .
This is big Piston
The color is : red and shape fill is : true Radius= 1234.4 Height=
55.6 Cylinder total surface Area= 4784554.150400002 volume= 2.6602121076224005E8. the cross sectional area of Piston = 4784554.150400002 shaftlength=1200.0 pressure=12.3 .
To clarify -- it seems like this is the situation:
You have one class (Cylider) that defines a method (getArea()) to do one thing. Another method on Cylider (toString()) calls that getArea() method.
Then, you sub-classed Chylidar with a child type (Piston) and overrode the getArea() function to do a different thing.
Now, when you're code in the Cylider class clls the getArea() method, you expected it to use the Cylider version of getArea() because the code was written in the same class, but in reality it used the overriden Piston version of getArea() because the object you were calling it on actually was a Piston.
This isn't really a bug or even a problem to solve -- it's just a function of how Java resolves method calls. It will pick the one that is most specific given the actual type of the object you are working with (even if it's not obvious at compile time what that type would be) not the one that is written closest to the sight of the caller.
There isn't really a way to get around this. I would take this as a sign that your design is bad -- or at least not idiomatic. Overriding functions is intended for you to give a different, more correct way to calculate the same idea for a different type, not just as a way to re-use function names.
The easiest change would probably be to just make a new method on Cylinder called getCylinderArea(). Cylider.getArea() could call this function by default, but you could call it explicity in Cylider.toString() if you wanted that function to only ever use the plain Cylinder method of calculating area.
Alternatively, Maybe Piston shouldn't actually be a subtype of Cylinder because, even though they share some characteristics, a Piston isn't substitute-able for a generic cylinder anywhere you would use a cylinder -- for example, when calculating the area. Look up the Substitution Principle for more.
Personally, though, I tend to stay away from inheritance altogether for this exact kind of reason. I would actually recommend just using interfaces and a flat hierarchy in this case instead.
This StackOverflow thread might be interesting if you want more detail on calling super methods.

Most efficient way of using toString() JAVA

I have 2 classes of shapes one is rectangle and the second is circle, both extend "shape" class.
I should print the relevant info from each class for example x, y represent a point which is relevant to all of the shapes and the color as well.
rectangle class has its width and height and circle has a radius.
I'm trying to use toString method in each class by overriding, using super and adding more info but one thing looks strange. should I create a new string builder object for each method? looks quite not right even though it works. Tried looking it up online but so far its either this or using a bunch of string. Am I missing something?
here is what I did in shape class:
public String toString() {
StringBuilder shapeBuilder = new StringBuilder();
System.out.println(shapeBuilder.append("The x axis is: ").append(x).append(" and the y axis is: ").append(y).append(" The color of ")
.append(this.getClass().getSimpleName()).append(" is ").append(color));
return shapeBuilder.toString();
}
rectangle class:
public String toString() {
super.toString();
StringBuilder rectangleBuilder = new StringBuilder();
System.out.println(rectangleBuilder.append("The height of the rectangle is: ").append(height)
.append(" And the width is: ").append(width));
return rectangleBuilder.toString();
}
circle class:
public String toString() {
super.toString();
StringBuilder circleBuilder = new StringBuilder();
System.out.println(circleBuilder.append("the radius of the circle is: ").append(getRadius()));
return circleBuilder.toString();
}
I'm calling them from main using object name.toString();
The obvious problems are
In your Rectangle and Circle class, you called super.toString() and do nothing with the result. There is no reason calling it. Or, I guess what you are trying to do is something like : (e.g. Rectangle )
public String toString() {
return super.toString()
+ " height " + this.height
+ " width " + this.width;
}
In your case, you do not need to explicitly use StringBuilder. Simply
e.g. Shape class
public String toString() {
return "The x axis is: " + x
+ " and the y axis is:" + y
+ " The color of " + this.getClass().getSimpleName()
+ " is " + color;
}
is good enough. Always-use-StringBuilder is not necessary better.
Use System.out.println(super.toString() to print/use super class toString().
Code Below:
public class Shape {
int x;
int y;
#Override
public String toString() {
return "Shape [x=" + x + ", y=" + y + "]";
}
}
public class Rectangle extends Shape{
double width,height;
#Override
public String toString() {
System.out.println(super.toString());
return "Rectangle [width=" + width + ", height=" + height + "]";
}
public static void main(String[] args) {
Rectangle rectangle=new Rectangle();
rectangle.x=10;
rectangle.y=30;
rectangle.width=20;
rectangle.height=100;
System.out.println(rectangle);
}
}

Setting up a toString() method for an array list

Sorry for what is probley a simple question but how would i go about setting up a toString() method for an array list?
is it as simple as
points = new ArrayList<Point>();
public String toString() {
return points.toString();}
which does not seem to be working for me, or would it be more complex since it is a array list? Because for some reason when i execute mine like this its only printing the first value or object.
P.S I'm trying to return all the values that i have already added to my list.
More in detail
constructer
public Cloud() {
points = new ArrayList<Point>();
}
add point
public void addPoint(Point p) { // done
if (points.contains(p)) {
// if p is already in the list it does nothing
} else {
points.add(p); // if p was not in the list it adds it to the end
}
}
toString
public String toString() {
return points.toString();
}
main
public static void main(String[] args) {
Cloud cloud = new Cloud();
cloud.setDebug(false);
System.out.println("cloud.debug OFF");
System.out.println("initial cloud: " + cloud.toString());
Point p1 = new Point(3.0, 1.0);
cloud.addPoint(p1);
Point p2 = new Point(2.0, 2.0);
cloud.addPoint(p2);
Point p3 = new Point(1.5, 1.5);
cloud.addPoint(p3);
Point p4 = new Point(3.0, 0.0);
cloud.addPoint(p4);
System.out.println("final cloud: " + cloud);
This is just printing final cloud: (3.0,1.0) while it should be printing final cloud: [(3.0,1.0), (2.0,2.0), (1.5,1.5), (3.0,0.0)]
edit: Points class
public class Point {
private double x;
private double y;
public static final double EPSILON = 1e-5;
public static boolean debug = false;
public Point(double x, double y) {
this.x = x;
this.y = y; // Done sets the x,y private types to the x,y type provided
// in the ()
}
public Point() {
this(0.0, 0.0); // calls the point (double x,double) constructer with
// the given arguments
} // inturn setting x and y == 0.0
public double getX() {
return x; // returns the private value of x when called in the main
// method
} // so it can't be changed by the user
public double getY() {
return y; // return the private value of y when called in the main
// method so it can't be changed
} // by the user
public String toString() {
return "(" + x + "," + y + ")"; // done by teacher sets the toString
// method and implemetns it
}
public boolean equals(Point p) {
if (Math.abs(this.getX()) - Math.abs(p.x) < EPSILON) {
return true; // checks if x - p.x is less than epsilon which covers
// the round off
}
if (Math.abs(this.getY()) - Math.abs(p.y) < EPSILON) {
return true; // checks if y-p.y is less than epsilon which covers
// the round off
}
return false; // both these methods test for equality using epsilon,
// becuae we are dealing with
} // doubles, so roundof can occur
public boolean equals(Object obj) { // this was given to us
if (obj instanceof Point) {
Point p = (Point) obj; // This method overrides the object equals
// method and the calls
return equals(p); // the clas's equals(point) method
}
return false;
}
// TODO Implement Point.euclidDist
/**
*
* #param p
* #return Euclidean distance of this point to point p
*/
public double euclidDist(Point p) {
double distance = 0;
double firstvalue;
double secondvalue;
distance = Math.sqrt(((this.getX() - p.x) * (this.getX() - p.x)) // calculate
// the
// distance
+ ((this.getY() - p.y) * (this.getY() - p.y))); // between the
// two points
// firstvalue= Math.pow(this.getX()-p.x, 2);
// secondvalue= Math.pow(this.getY()-p.y, 2);
// distance = Math.sqrt(firstvalue + secondvalue);
return distance;
}
/**
* #param args
* : no args
*/
public static void main(String[] args) {
// test all methods
if (debug)
System.out.println("debug ON");
else
System.out.println("debug OFF");
System.out.println("EPSILON: " + Point.EPSILON);
Point origin = new Point();
Point p1 = new Point(0.0, 4.0);
Point p2 = new Point(3.0000001, 3.9999999);
Point p3 = new Point(3.0, 4.0);
Point p4 = new Point(0.0, 5.0);
Point p5 = new Point(12.0, 0.0);
System.out.println("origin: " + origin);
System.out.println("p1: " + p1);
System.out.println("p2: " + p2);
System.out.println("p3: " + p3);
System.out.println("p4: " + p4);
System.out.println("p5: " + p5);
if (p2.equals(p3))
System.out.println(p2 + " equals " + p3);
else
System.out.println(p2 + " does not equal " + p3);
System.out.println("Euclidean distance between " + origin + " and "
+ p1 + ": " + origin.euclidDist(p1));
System.out.println("Euclidean distance between " + p1 + " and " + p3
+ ": " + p1.euclidDist(p3));
System.out.println("Euclidean distance between " + p3 + " and "
+ origin + ": " + p3.euclidDist(origin));
System.out.println("Euclidean distance between " + p4 + " and " + p5
+ ": " + p4.euclidDist(p5));
}
}
You can only create toString() method overrides in classes of yours, not in other classes that you're not overriding. ArrayList already has a valid toString() method that is useful. You will just need to make sure that the items held by the List are from a class that also has a valid toString() method.
Note you state:
which does not seem to be working for me...
Because for some reason when i execute mine like this its only printing the first value or object.
This suggests that you don't have a toString() problem, but that you actually have another completely different problem with your program, that you're not adding objects to the list correctly. You need to do more debugging and show more pertinent code.
Edit
I'm guessing that your Point class's contains(...) method is erroneous, that it is returning true when it should be returning false. Please show us the Point class.
Edit 3 (deleted edit 2)
Your equals is wrong:
This is OK:
public boolean equals(Object obj) { // this was given to us
if (obj instanceof Point) {
Point p = (Point) obj; // This method overrides the object equals
// method and the calls
return equals(p); // the clas's equals(point) method
}
return false;
}
But here, you return equals if either x's or y's closely match and that shouldn't be. You should only return true if BOTH closely match:
public boolean equals(Point p) {
if (Math.abs(this.getX()) - Math.abs(p.x) < EPSILON) {
return true; // checks if x - p.x is less than epsilon which covers
// the round off
}
if (Math.abs(this.getY()) - Math.abs(p.y) < EPSILON) {
return true; // checks if y-p.y is less than epsilon which covers
// the round off
}
return false; // both these methods test for equality using epsilon,
// becuae we are dealing with
} // doubles, so roundof can occur
Also you're using Math.abs(...) incorrectly. It should go around the subtraction statement, not around each variable.

toString() and accessors

public class Fan {
public static void main(String[] args){
Fan fan1 = new Fan();
fan1.setSpeed(FAST);
fan1.setRadius(10);
fan1.setColor("yellow");
fan1.setOn(true);
System.out.println(fan1.toString());
}
// fan speed variables
final static int SLOW = 1;
final static int MEDIUM = 2;
final static int FAST = 3;
// Other fan variables
private int speed;
private boolean on; // true means on
private double radius; // radius of fan
String color;
// No-arg constructor
public void Fan(){
speed = SLOW;
on = false;
radius = 5;
color = "blue";
}
// Mutator methods
public void setSpeed(int newSpeed){
if(newSpeed < 0)
System.out.println("Illegal speed!");
else
speed = newSpeed;
}
public void setOn(boolean newOn){
on = newOn;
}
public void setRadius(int newRadius){
if(newRadius < 0)
System.out.println("Illegal radius!");
else
radius = newRadius;
}
public void setColor(String newColor){
color = newColor;
}
// Accessor methods
public int getSpeed(){
return speed;
}
public boolean getOn(){
return on;
}
public double getRadius(){
return radius;
}
public String getColor(){
return color;
}
// toString method to output Fan data
public String toString(){
if(on = false)
return "Fan is off.";
else
return "Fan Properties:\n" + "Fan speed: " + speed + "\n"
+ "Color: " + color + "\n"
+ "Radius: " + radius + "\n";
}
}
The above piece of code is simple but I was wondering how the toString method uses the on variable even though I didn't supply parameters for that method. Also, why do we not need to invoke get methods in the main class and only need to invoke the set methods? (please explain how each method invokes one another until the final output)
Thanks a lot!
As far as you are in this class body you can access everything (except for static can not access non-static). That means that you can easily set and get variables like that:
var = <value>;
System.out.println(var);
However nobody stops you from using the accessor methods - getter and setters. It is just not required.
One final note:
if(on = false)
This will always fail - it does assignment to false and then checks the newly assigned value (which is false). You need to check for equality here. Like that:
if(on == false)
Or even better:
if(!on)
I just copied-pasted your code into a new file and compiled it. It compiled and ran. The output was
$ java Fan
Fan Properties:
Fan speed: 3
Color: yellow
Radius: 10.0
This is because the comparison in your toString method is wrong. It should be as following:
public String toString(){
if(on)
return "Fan Properties:\n" + "Fan speed: " + speed + "\n"
+ "Color: " + color + "\n"
+ "Radius: " + radius + "\n";
else
return "Fan is off.";
}

Categories