why did this constructor chaining cause stack overflow(java) - java

So I have the code below but it caused java.lang.StackOverFlowError.
I guess maybe creating an new object inside the second constructor may
have caused an infinite loop or something. But I don't fully understand
why this happened. Could someone explain it to me? I'd appreciate it!
private double x;
private double y;
private double z;
private double[] elements;
/**
* Creates a 3D vector from an array
* #param v array containing 3 components of the desired vector
*/
public Vector3(double[] v) {
this(v[0], v[1], v[2]);
}
/**
* Creates a 3D vector from 3 numeric scalar components
* #param x x coordinate
* #param y y coordinate
* #param z z coordinate
*/
public Vector3(double x, double y, double z) {
this(new Vector3(x, y, z));
}
/**
* Clones an existing vector
* #param old an existing Vector3 object
*/
public Vector3(Vector3 old) {
x = old.x;
y = old.y;
z = old.z;
elements = new double[3];
elements[0] = x;
elements[1] = y;
elements[2] = z;
}

public Vector3(double x, double y, double z) {
this(new Vector3(x, y, z));
}
I'm not sure what you're up to do, but it seems you're calling the Vector3 constructor in itself. This is causing the infinite loop.

In the constructor
public Vector3(double x, double y, double z) {
this(new Vector3(x, y, z));
}
you are calling the same constructor again and again (i.e. new Vector3(x, y, z)). That causes the SOE. This happens before the copy constructor with the call to this(...) even has a chance.
Assuming the following class
public class Vector3 {
// No need for an array. Or if you want an array, discard the doubles.
double x;
double y;
double z;
public double getX() { return x; }
public double getY() { return y; }
public double getZ() { return z; }
}
the correct way to build up constructors is the following:
1) Start with a constructor that builds up a whole instance with all elementary data:
public Vector3(double x, double y, double z) {
this.x = x;
this.y = y;
this.z = z;
}
2) If you want to add some other convenience constructors, do it his way:
public Vector3(double[] elements) {
this(elements[0], elements[1], elements[2]);
}
3) A copy constructor can be handled the same way:
public Vector3(Vector3 origin) {
this(origin.getX(), origin.getY(), origin.getZ());
}
All the other constructors can be built by calling the first constructor!

Related

Java - Implement Cloneable or add a constructor?

Hey I'm actually working with a custom Vector class on Java,
public class Vector {
private double X;
private double Y;
public Vector(double x, double y) {
this.X = x;
this.Y = y;
}
public void setX(double x) {
this.X = x;
}
public double getX(double x) {
return this.X;
}
public void setY(double y) {
this.Y = y;
}
public double getY(double y) {
return this.Y;
}
}
I wanted to add the multiply() method that would return this vector * by the specified factor like that,
public void multiply(double factor) {
this.X *= factor;
this.Y *= factor;
}
The thing is, when I use a function requiring a vector, I'd like to use it like
doSomething(ancientVector.multiply(-1D));
but the jvm isn't satisfied because the arg I send to the function is a void...
How could I also do to make it clean, should I implement Cloneable or create another constructor working the way multiply does?
doSomething(ancientVector.multiply(-1D));
OR add
public Vector(Vector previous, double mFactor) {
this.X *= previous.getX() * mFactor;
this.Y *= previous.getY() * mFactor;
}
I would keep the class immutable and return a new Vector:
public Vector multiply(double factor) {
return new Vector(X * factor, Y * factor);
}
You could do as #Basti said or you could also return a new instance of your Vector:
public Vector multiply(double factor) {
return new Vector (this.X * factor, this.Y * factor);
}
This way when any change is made to the result of your multiply function it does not affect the initial vector object.
Your Vector will have various operations (you've started with multiply) and its usage looks similar to Java API classes such as BigDecimal. I would therefore recommend following its lead, and make the class immutable. That means all its fields should be final:
public class Vector {
private final double x, y; // Note: final. And use lowercase.
public Vector(double x, double y) {
this.x = x;
this.y = y;
}
// Note: no setters!
public double getX() { // Note: no argument.
return x;
}
public double getY() {
return y;
}
public Vector multiply(double factor) {
return new Vector(x*factor, y*factor);
}
}
One of the advantages of immutable classes is that they are purely value-based so you don't have to worry about copy constuctors or cloning. (By the way, Cloneable is hardly ever used nowadays – copy constructors are preferred – except perhaps for arrays.) Instead of copying, just use assignment: Vector secondVector = firstVector;.

Calculate distance between two points in java

I'm kind of new to Java, and trying to write a code that calculate the distance of two points 2 and 3, and scale of 10. Somehow, it does not work. Can you give me a hint, so I can fix the code?
import java.lang.Math;
public class Point {
int x, y;
public Point (int x, int y){
this.x = x;
this.y = y;
}
public float scale(int factor) {
new Point(x * factor, y * factor);
return factor;
}
public float distance(){
double distance = Math.sqrt(x * x + y * y);
return distance;
}
public void main(String[] args) {
float p = new Point(2,3).scale(10);
System.out.println(distance);
}
}
In scale you are creating a new point with the scaled values and doing nothing with it. You're leaving x and y of the point in question untouched.
You probably mean to multiply x and y by factor, rather than creating a new point.
Also you're printing a variable named distance, which does not exist (so this probably doesnt even compile), rather than calling the method named distance() and printing its returned value.
public class Point {
int x, y;
public Point (int x, int y){
this.x = x;
this.y = y;
}
public static Point scalePoint(Point p, int factor) { //scale a given point p by a given factor
Point scaledPoint = new Point(p.x * factor, p.y * factor); //by multipling the x and y value with the factor
return scaledPoint; //and return the new scaled point
}
public static double calculateDistance(Point p1, Point p2){ //to calculate the distance between two points
double distance = Math.sqrt(p1.x * p2.x + p1.y * p2.y); //send the two points as parameter to this method
return distance; //and return the distance between this two as a double value
}
public static void main(String[] args) {
Point p = new Point(2,3);
Point scaledPoint = scalePoint(p, 10);
double distance = calculateDistance(p, scaledPoint);
System.out.println(distance);
}
}
At the moment your distance method is calculating the distance of a point from the origin (i.e. point 0,0). It would make more sense if you made that explicit:
class Point {
private static final Point ORIGIN = new Point(0, 0);
private final int x;
private final int y;
public float distanceTo(Point other) {
float xDelta = other.x - this.x;
float yDelta = other.y - this.y;
return Math.sqrt(xDelta * xDelta + yDelta * yDelta);
}
public Point scale(float factor) {
return new Point(x * factor, y * factor);
}
}
Then finding the distance to the origin becomes point.distanceTo(Point.ORIGIN) which makes the intent clearer.

Why does my class's test program return 0.0 for my answers?

package Geometry;
public class TestGeometryPoint {
public static void main(String[] args) {
//Creates the object PointA and Assigns values
Point pA = new Point(); //PointA(0, 0)
pA.setX(2.0); //PointA(2.0, 0)
pA.setY(5.0); //PointA(2.0, 5.0)
//Creates the object PointB and Assigns values
Point pB = new Point(4.0, 6.1); //PointB(4.0, 6.1)
//Calculates the distance between PointA and PointB
double d = pA.distance(4.0, 6.1); //Distance from class to a set of coordinates
double dP = pA.distance(pB); //Distance from class to another point
double dPtP = Point.distance(pA, pB); //Distance from point to point
//Prints the result of the calculations
System.out.println("Distance between Point A & B: " + d);
System.out.println("Distance between Point A & B: " + dP);
System.out.println("Distance between Point A & B: " + dPtP);
}
}
This is my Test Class and my Point class below.
package Geometry;
public class Point {
//Initializes the coordinates for a point on a graph with the values of x and y
private static double x;
private static double y;
//Defualt Constructor
public Point() {
x = 0;
y = 0;
}
//Point Constructor
public Point(double x, double y) {
this.x = x;
this.y = y;
}
//Returns the x value
public double getX() {
return x;
}
//Changes the x value
public void setX(double x) {
Point.x = x;
}
//Returns the y value
public double getY() {
return y;
}
//Changes the y value
public void setY(double y) {
Point.y = y;
}
//Calculates the distance between the class's point coordinates and another set of point coordinates
public double distance(double x0, double y0) {
double distance = (Math.sqrt(((x0 - x) * 2.0) + ((y0 - y) * 2.0)));
return distance;
}
//Calculates the distance between the class's point and another Point class's location
public double distance(Point p) {
double distance = (Math.sqrt(((p.getX() - x) * (p.getX() - x)) + ((p.getY() - y) * (p.getY() - y))));
return distance;
}
//Calculates the distance between a Point class's location and another Point class's location
public static double distance(Point p1, Point p2) {
double distance = (Math.sqrt((Math.pow((p2.getX() - p1.getX()), 2.0) + (Math.pow((p2.getY() - p1.getY()), 2.0)))));
return distance;
}
}
d, dP, dPtP: all return 0.0 when compiled and run, but I have no idea why as I have tried changing code and checking my math when calculating distance. I think I might just need a new set of eyes to take a look at it.
I believe since your x and y variables are static, they belong to the class Point as a whole. When you create a Point(2,5);
You set the static variable of the class Point to be 2 and 5 and then, you create another Point(4,6) You set the same static value of x and y to be 4,6.
Therefore, comparing the distance between the same two Point are 0.
The right code for the class Point would be like so
public class Point {
//Initializes the coordinates for a point on a graph with the values of x and y
private double x;
private double y;
//Defualt Constructor
public Point() {
x = 0;
y = 0;
}
//Point Constructor
public Point(double x, double y) {
this.x = x;
this.y = y;
}
//Returns the x value
public double getX() {
return x;
}
//Changes the x value
public void setX(double x) {
this.x = x;
}
//Returns the y value
public double getY() {
return y;
}
//Changes the y value
public void setY(double y) {
this.y = y;
}
//Calculates the distance between the class's point coordinates and another set of point coordinates
public double distance(double x0, double y0) {
double distance = (Math.sqrt(((x0 - x) * 2.0) + ((y0 - y) * 2.0)));
return distance;
}
//Calculates the distance between the class's point and another Point class's location
public double distance(Point p) {
double distance = (Math.sqrt(((p.getX() - x) * (p.getX() - x)) + ((p.getY() - y) * (p.getY() - y))));
return distance;
}
//Calculates the distance between a Point class's location and another Point class's location
public static double distance(Point p1, Point p2) {
double distance = (Math.sqrt((Math.pow((p2.getX() - p1.getX()), 2.0) + (Math.pow((p2.getY() - p1.getY()), 2.0)))));
return distance;
Your problem is that you are confusing static and non-static fields.
By putting that little static on your field declarations you are saying: all instances of this class should be seeing the exact same variables.
So, when you create two points
p1 = new Point(5, 5);
p2 = new Point(10, 10);
the declaration of p2 "overrides" the 5-5 from p1 ... because, as said: all Points are using the same x and y.
Thus, solution: simply drop that keyword from the definition of x and y. Then each point has is very own x and y.
And, more importantly: understand that each and any character in your source code matters. This means: you better understand each and any concept that your source code is making use of!

Java variable setting through method

I have a method which takes in 4 floats and modifies the value. Now I would like to set the floats of the parent class to the value that the method took in. Some code:
public void influence(float x, float y, float w, float h){
x += 5; y += 5; w += 5; h += 5;
}
Now that would be called from the parent class like this:
float x = 5, y = 5, w = 5, h = 5;
influence(x, y, w, h);
I would like to set the floats in the parent to the modified method. I know I could return a float[] and then manually set the floats of the parent class to that array but is there a better way to do this? I could also use a class like Rect but that would be like an array.
Java does not have a way to pass a reference to a primitive. However, in your situation it would probably be better to avoid it anyway: it appears that the four variables are related to each other.
When several variables are related, they should be instance variables of a single object. Your object probably looks like a rectangular box that has the origin of (x, y), height h, and width w. Make a class for it, and let the method change that class, or return a new instance:
class Rect {
private final float x, y, w, h;
public float getX() { return x; }
public float getY() { return y; }
public float getW() { return w; }
public float getH() { return h; }
public Rect(float x, float y, float w, float h) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
}
}
Then you can write a method returning a new Rect
public Rect influence(Rect inputRect) {
...
}
or make Rect mutable, and let influence modify its values.
You can't change primitives in Java like that because everything in Jave is passed by value - but you can store the value in an array and pass it:
public void influence(float[] arr){
for (int i=0; i<arr.length; i++){
arr[i] += 5;
}
}

Having 2 compiling errors in my java program . clarification please

The errors I am getting are
1 a cannot find symbol error
and
2 "constructor circle, in class circle cannot be applied to given types. "
At this point I just can seem to grasp what I did wrong.
public class Circle {
private double radius;
public Circle (double radius) {
radius = radius;
}
public double getRadius() {
return radius;
}
public double getArea() {
return radius * radius * Math.PI;
}
}
class B extends Circle {
private double length;
B (double radius, double length) {
Circle (radius);
length = length;
}
//**override getArea()*/
public double getArea() {
return getArea() * length;
}
}
At super-class Circle use this to refer current instance.
public Circle (double radius) {
this.radius = radius;// Use this
}
At sub-class use super() to access super-class constructor. Change from
B (double radius, double length) {
Circle (radius);// This is compilation error.
length = length;
}
To
B (double radius, double length) {
super(radius); // This is the way to access super-clss constructor.
this.length = length; //Use this to refer current instance length.
}
I'd recommend you to change:
radius = radius;
to
this.radius = radius; // 'this' makes reference to the actual instance
And change the B constructor to:
public Test(double radius, double length)
{
super(radius); // Calls super class constructor
this.length = length;
}

Categories

Resources