This is an instance method from a Rectangle class where we modify the x and y coordinates of the rectangle and its width and height
public void modify(int newX, int y, int width, int h) {
int x = newX;
this.y = y;
width = width;
this.height = height;
}
Rectangle r3 = new Rectangle(0, 0, 10, 10);
r3.modify(5, 5, 50, 50);
System.out.print(r3.getX() + " " + r3.getY() + " ");
System.out.println(r3.getWidth() + " " + r3.getHeight());
I have this code and I know that the output is 0 5 10 10 but i'm not entirely sure why. can anyone explain why?
public void modify(int newX, int y, int width, int h) {
int x = newX; // the value isn't saved to the class members
this.y = y; // this is saved, hence you see the change in the y value
width = width; // meaningless, the variable is overwritten with it's own value
this.height = height; // who is height? the function receives h
}
You have created a new object of type "int" for X within the modify method. This means that it only exists within that method since you're not passing it by reference. So, the newX value is only 5 within the modify method, but does not exist as '5' outside of it. this.y works fine because you've called that specific instance of the object and modified it's value. Therefore, it's retained outside the method. 'width = width' doesn't work because you're simply assigning 50=50 (since you've inputted 50 as the width). 'this.height = h' would be fine, but you've said 'this.height = height'. But, from the code you've given, 'height' doesn't exist.
y is the only instance variable that is actually modified in the modify method. The other the arguments passed in have no net effect on the state of the object.
Actually, the code shouldn't compile. height isn't defined in your method call. Unless this is another property that you didn't include in your code snippet.
int x = newX creates a new int named x that you then do nothing with. That's why r3.getX() returns 0, since you never modified it.
this.y = y changes the value of the field y within the Rectangle class. This is why this change is shown in your output as 5.
width = width changes the method parameter named width to itself. It doesn't change the value, but it also doesn't set the field width within Rectangle. No change shown, original value of 10 prints.
If height is a field elsewhere, then it makes sense that r3.getHeight() wouldn't update the field, since the parameter in the method call is for h, not height. If not, then I don't know how the code compiles since height isn't mentioned anywhere.
The "int x = newX" line creates a variable "x" on the stack that exists only for the duration of the current method call.
"this.x" would refer to the "x" created by the classes constructor. Which is probably what "getX()" returns.
This code shows the difference between the function stack variable and object variable. For function modify, the four passing variables are on the stack. The line declares a stack variable x and set its value as newX. The second line uses the object variable this.y and set to passing variable y. The third line is to assign the width to its self on stack. The fourth line uses the object variable height and assign to its self. Once the program goes out of the scope of function modify, all its stack variables' value are whacked. So the result is 0 5 10 10 because only the second line which is not stack variable this.y retains its value after calling function modify.
I would venture to say your issue is in how you are assigning the new values of x, y, width and height to your rectangle object.
Assuming that your modify method is in the rectangle class your code currently looks like this (I added comments on the mistakes:
public void modify(int newX, int y, int width, int h) {
int x = newX; //you are declaring a new x here...not assigning newX to rectangle's x
this.y = y; //this is correct
width = width; //here you're just assigning the parameter width its current value
this.height = height; //here you are assigning the rectangles height value to itself
}
I would HIGHLY advise finding a naming convention and sticking with it as it would help tremendously here.
Try something like this:
public void modify(int x, int y, int w, int h) { //changed names of parameters
this.x = x; //removed the int type declaration and used this. prefix
this.y = y; //changed nothing
this.width = w; //adjusted for renamed parameter, used this. prefix
this.height = h; // adjusted for renamed parameter, again used this. prefix
}
As you can see, sticking to a convention makes the code less confusing and easier to read. This also allows you to see your mistakes more easily as they will usually stick out from your convention like a sore thumb. Don't worry it comes with practice.
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 months ago.
Improve this question
public class Wall {
private double width;
private double height;
public Wall() {}
public Wall(double width, double height) {
this.setHeight(height); // using method to set the required fields. //This method is called with unexpected behavior.
this.setWidth(width); // This is not getting called?
}
public double getWidth() {
return width;
}
public void setWidth(double width) {
if (width <= 0) {
this.width = 0;
System.out.println("INVALID VALUE - The width of the wall is updated to :" + 0.0);
} else {
this.width = width;
System.out.println("The width of the wall is updated to :" + width);
}
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
if (height <= 0) {
this.height = 0;
System.out.println("INVALID VALUE - The width of the wall is updated to :" + 0.0);
} else {
this.height = height;
System.out.println("The height of the wall is updated to :" + height);
}
}
public double getArea() {
return width * height;
}
}
//OUTPUT
The width of the wall is updated to :10.0 \\ Expected
INVALID VALUE - The width of the wall is updated to :0.0 \\ not expected
//OUTPUT when parameter order in constructor is reversed
INVALID VALUE - The width of the wall is updated to :0.0 \\expected
The height of the wall is updated to :10.0 \\expected
The goal was to avoid code repetition and I chose to use the setter method in constructor. Also assuming since I am using methods and providing appropriate parameters, the order of the parameter should not matter.
I am not sure if it is supposed to work that way. I see that the method is being called with unexpected behavior.
Few doubts I have regarding the above
Not all methods are getting called in the constructor
Can these setter methods be static and perform operation on the object being created?
What would be the right way to do this?
Thank you
I see that the method is being called with unexpected behavior.
setHeight() actually performs as expected but it is not implemented as you'd expect it. You probably copied it from setWidth() and forgot to change the message so it would print "INVALID VALUE - The width of the wall is updated to : xxx".
the order of the parameter should not matter
The order in which you define the parameters doesn't matter from a technical point of view (unless you have a vargs parameter which needs to be last). However the order of definition leads to the requirement of providing values in the same order when calling the constructor.
Example: Wall(double width, double height) defines the 1st parameter is width and the 2nd is height.
Assume the following:
double width = 5.0;
double height = 7.0;
Wall w = new Wall(height, width);
Here, the names of the parameters don't matter but order does, i.e. w now has a width of 7 and a height of 5 even though the parameters were named otherwise.
What shouldn't matter in most cases is the order in which you call the setters inside the constructor - as long as they're independent.
This means the following 2 should be equivalent:
public Wall(double width, double height) {
this.setHeight(height);
this.setWidth(width);
}
public Wall(double width, double height) {
this.setWidth(width);
this.setHeight(height);
}
When would order matter? If setters were depending on it - not a good style though. Suppose setHeight() would check that height > width. Now if you'd not call setWidth() first setHeight() might behave differently. However, I repeat: this it not good style and should be avoided!
Not all methods are getting called in the constructor
Not sure what you're referring to but constructors don't have to call any method nor do you have to call all the setters there. It really depends on what you want to achieve.
Use constructors for mandatory parameters and setters for mutable ones (and potentially optional). Mutable parameters are those that could be changed after constructing an object, immutable ones should not change - there shouldn't be any setter for those (ideally declare those final and the compiler will complain about setters for those).
Summary:
mandatory + immutable parameters: use constructor only
mandatory + mutable parameters: use constructor which can call setters
optional + mutable parameters: use setters
optional + immutable parameters: use constructor only, potentially via constructor overloads
Can these setter methods be static and perform operation on the object being created?
No, setters should never be static because you'd need to pass the object anyway and thus it's cleaner to just have the setters there.
However, a constructor can call static methods if necessary. Suppose you have a condition to check that width < height which you'd want to call in the constructor and the setters. This could then look like this (simplified and lacking a lot of best practices to keep things simple):
//example of constructor calling the static method
public Wall(double width, double height) {
//check the condition on the input parameters
if( !checkCondition(width, height) ) {
throw new IllegalArgumentException("width >= height");
}
this.setHeight(height);
this.setWidth(width);
}
//example of setter calling the static method
public void setWidth(double width) {
//only set if the condition is met
if(checkCondition(width, this.height) {
//rest of your code
} else {
System.err.println("width would be < height, thus not updating width");
}
}
private static boolean checkCondition(double width, double height) {
return width < height;
}
If a class contains an object as an instance variable, and one of the constructors includes an object of the same type as a parameter, is it best practice to assign the argument to the instance variable, or to create a new object from the argument, and assign THE NEW OBJECT to the instance variable.
Here's an example from an exercise I'm working through:
public class MyCircle {
private MyPoint center; //contains variables int x and int y
private int radius;
//Non-controversial Constructor:
public MyCircle(int x, int y, int radius ) {
//creates new center using a valid MyPoint constructor
this.center = new MyPoint(x, y);
this.radius = radius;
}
//OPTION A
public MyCircle( MyPoint center, int radius ) {
this.center = center;
this.radius = radius;
}
//OPTION B
public MyCircle( MyPoint center, int radius ){
this.center = new MyPoint( center.getX(), center.getY() );
this.radius = radius;
}
}
Initially, I typed option A, but I thought that this could create buggy behavior if this.center referenced an existing object that could be modified indirectly unintentionally. The alternative way of thinking about it, I guess, is that this creates an avenue for creating multiple objects that share a center, and moving a single center would intentionally move all circles that share that center.
Since Java has no pointers (at least not for developers) that option will be discarded and is not the way to go..
Now this:
public MyCircle( MyPoint center, int radius ) {
this.center = center;
this.radius = radius; }
Is in my opinion better, you can just assign the center and don't need to make a risky copy of the class MyPoint... And I say risky because if you want to do that you should at least check the non-null condition of that parameter....
You can for sure think... what if center is null in option A, you are right, that can happen, then you can take care of it by either throwing an illegalparameterexception, or just assigning that object to a default value. ..
But as I said before is my opinion..
I think it depends on your program. If you want the circle to have a reference to the MyPoint object, then you must pass it. Otherwise, why not pass in the actually x and y values themselves.
For example, option B can be written as:
public MyCircle(int x, int y, int radius) {
// rest
}
both options are fine, but as you told, an object may change in the time, the option A is ok when you want to modify the center in more than one object at the same time, for example in an List of Circles, but if you want to have unique and independient center points, option B is correct. So you why don't you have both constructors and use one or another depending many cases in your app, use whatever you want you consider better, keep both, it is my advice.
Hope it helps to you.
Recursion always has been something I have a hard time with. I have a test tomorrow and he said there will be some Recursion on the test so I want to be prepared.
The problem I am trying to do says this:
Given a class Rectangle with instance variables width and height, provide a recursive getArea() method. Construct a rectangle whose width is one less than the original and call its getArea method.
So I know that in recursion you end up calling the method inside itself with a simplified rendition. Like, I know somewhere in getArea(int n) I will have to call getArea(n - 1). I am just not sure what to do with width and height.
So I have this:
public int getArea()
{
if (width == 1) {
// Base case here. Not sure what to do for this.
return 1; // Maybe? I'm not sure.
} else {
Rectangle smallerRect = new Rectangle (width - 1);
int smallerArea = smallerRect.getArea();
return smallerArea + height + width;
}
}
Can anyone help me better understand recursion or maybe how to go about thinking through a recursive function? Thanks.
You've got the recursion itself right, with a base case and a recursive case, and a correct reduction of the parameter in the recursive call (except that, as the commenters have noted, you also need to specify the height of the new rectangle). It's only the geometry that needs fixing: height doesn't change during the recursion; what is the area of the base case rectangle, which has got width 1 and height height? And if you are told the area of the rectangle with width width - 1 and height height, how much extra area do you get by adding a strip of width 1 and height height?
For later use: while mathematically correct, this is a terrible way to compute the area of a rectangle, so please don't do this outside of exam/homework situations :-)
Something like this perhaps? It's basically just multiplying width by height with recursion...
public int getArea() {
return getArea(width);
}
private int getArea(int x) {
return x == 0 ? 0 : height + getArea(x-1);
}
public int getArea()
{
if (width == 1) {
// Base case
return height; // Area = width(1)*height
} else {
Rectangle smallerRect = new Rectangle (width - 1, height);
int smallerArea = smallerRect.getArea();
return smallerArea + height;
}
}
I know there is an easy solution to this problem but it's driving me crazy. Why is there an error when I want to print the new Rectangle? any help appreciated!
public class Rectangle {
public Rectangle(int x, int y, int width, int length) {
x = 5;
y = 10;
width = 20;
length = 30;
Rectangle box = new Rectangle(5, 10, 20, 30);
System.out.println(new Rectangle());
}
}
There are several problems with your code. First, you may not want to instantiate a Rectangle in the constructor of Rectangle as will lead to infinite recursion. The second problem is that you are calling a constructor that does not exist.
When you write:
new Rectangle()
the Java compiler will look for a constructor in the Rectangle class that accepts no arguments. But your code does not have such a constructor. You can add one like this:
public Rectangle(){
//Your code here to instantiate a default rectangle
}
Usually a constructor is used to set the values of the instance variables in a class rather than to execute code the way you have written it. You can move those lines that are creating rectangles into a main method to test the code.
Here is some code that does what I think you want it to:
public class Rectangle
{
int x, y, width, length; //declares the class's fields
public Rectangle(int x, int y, int width, int length)
{
this.x = x; //initializes the field x to the value of the local variable x
this.y = y; //initializes the field y to the value of the local variable y
this.width = width; //initializes the field width to the value of the local variable width
this.length = length; //initializes the field length to the value of the local variable length
System.out.println(this); //prints this object. should look similar to "Rectangle#1246889"
}
}
Please take a basic java tutorial (e.g. Providing Constructors for Your Classes), it will make your life easier.
You are calling a non-parameterized/default constructor from a parameterized constructor. The JVM in this case unable to create the default constructor. Hence in this case you need to include non-parameterized constructor explicitly into your class.
public class Rectangle {
public Rectangle(int x, int y, int width, int length) {
x = 5;
y = 10;
width = 20;
length = 30;
Rectangle box = new Rectangle(5, 10, 20, 30);
System.out.println(new Rectangle());
}
public Rectangle(){}
}
This will be error free.
First, the code (as you have provided it) can not possibly compile: you haven't declared x, y, width and height as member variables (fields) of your Rectangle. E.g.
// I'm assuming you want these private and final (I would)
private final int x, y, width, height;
Alternative, for a quick hack:
int x, y, width, height;
You are also trying to call a 0-argument constructor on your println line. Your class doesn't have a 0-argument constructor; it has a 4-argument constructor. I suspect (as noted above) you really want to print this.
But that wouldn't help much, on its own, unless you add an appropriate toString method to your class. E.g.:
public String toString() {
StringBuilder sb = new StringBuilder("Rectangle: ");
sb.append("x=").append(x);
sb.append(", y=").append(y);
sb.append(", width=").append(width);
sb.append(", height=").append(height);
return sb.toString();
}
You might want to think about implementing equals() and hashCode() too, if you choose to make this class immutable (I would). You can ixquick* or duckduckgo* this - there are plenty of explanations around.
[*] They are search engines: I don't use google.
I don't know how to complete this. I'm learning by myself and I found this exercise where you have a class for a rectangle like this:
public class Rectangulo {
private int x, y, width, heigth;
public Rectangulo(int x, int y, int width, int heigth){
this.x = x;
this.y = y;
this.width = width;
this.heigth = heigth;
}
public boolean isOverlaping(Rectangulo r1, Rectangulo r2){
}
And I have to complete the method so it returns true if the 2 rectangles are overlapping / colliding or false if they aren't. Can you give me any guide to help me think this problem, or tips?
I don't have to use the intersects method.
Thanks!
If you look at the method, you're provided with two rectangle objects as arguments, r1 & r2. Each instance has its specific value for x,y, width and height. You can use these values to determine whether the two rectangles collide or overlap
For your specific doubt, you might want to read the javadoc for Rectangle.. This will help you understand how a rectangle is created in Java