Help with cloning method
I'm almost done with this project which involves converting between Celsius, Fahrenheit, and Kelvin and the last thing I need is to figure out the cloning method. The task is "clone, which takes no formal parameters and returns a reference to a newly created Temperature object that has the same value and scale as the object of which it is a clone ". My code compiles, but when run in the client program, i recieve an error of java.lang.StackOverflowError at Temperature.clone(Temperature.java:134)
public class Temperature {
private double value;
private String scale;
public Temperature() { // default constructor
this.value = 0;
this.scale = "C";
}
public Temperature(double value, String scale) {
this.value = value;
this.scale = scale;
}
public double getValue() {
return this.value;
}
public String getScale() {
return this.scale;
}
public double getCelsius() {
if (scale.equalsIgnoreCase("C")) {
return this.value;
} else if (scale.equalsIgnoreCase("F")) {
double faren = ((this.value - 32) * (5 / 9));
return faren;
} else {
double kelvin = (this.value - 273.15);
return kelvin;
}
} // end getCelcius
public double getFaren() {
if (scale.equalsIgnoreCase("F")) {
return this.value;
} else if (scale.equalsIgnoreCase("C")) {
double celsius = ((this.value * 1.8) + 32);
return celsius;
} else {
double kelvin = ((this.value * 1.8) - 459.67);
return kelvin;
}
} // ene getFaren
public double getKelvin() {
if (scale.equalsIgno开发者_如何学JAVAreCase("K")) {
return this.value;
} else if (scale.equalsIgnoreCase("C")) {
double celsius = (this.value + 273.15);
return celsius;
} else {
double faren = ((this.value + 459.67) * (5 / 9));
return faren;
}
} // end getKelvin
public void setTemperature(Temperature t) {
this.value = t.value;
}
public void setType(double degree, String measure) {
this.value = degree;
this.scale = measure;
}
public void setValue(double degree) {
this.value = degree;
}
public void setScale(String measure) {
this.scale = measure;
}
public double convertToCelsius() {
this.scale = "C";
return this.value = getCelsius();
}
public double convertToFaren() {
this.scale = "F";
return this.value = getFaren();
}
public double convertToKelvin() {
this.scale = "K";
return this.value = getKelvin();
}
public Temperature clone() {
this.value = value;
this.scale = scale;
return clone();
}
}
The cloning method is the last method, so any help would really be appreciated. I'm not sure where I'm going wrong! This is my first time using this website, so apologies for the formatting!
I don't want to give you the answer to a homework project, that's frowned upon. However, the problems with your clone() method are hard to be... vague about.
public Temperature clone()
The method header looks great. You're returning a Temperature type, it's publicly accessible.
this.value = value;
this.scale = scale;
Do you know what the 'this' keyword does? It refers to the object that the method is called on. So, if I have a Temperature object 'a' and I want to call a.clone(), this will set a's value equal to... a's value.
return clone()
Here's the part that shows your big problem. What are you actually telling java to do here? You're telling it to return whatever the clone() method returns. Which means that clone will call itself, which will again call itself... on to stack overflow. This is a recursive loop that can't exit.
Remember, you want clone() to return a new Temperature object.
You accidentally made clone()
a recursive method without a means of terminating.
Also, Object.clone()
will only return a shallow copy. If you're attempting to return a deep copy, I'd recommend using a copy constructor.
The reason you are getting a stack overflow is because of this line:
return clone();
Have you learned about recursion yet? This line is calling the clone method from inside the clone method... which keeps happening over and over and over... well, until the stack runs out of space!
You want to return a new object, rather than returning clone()
.
You do not need to do anything to primitive fields and fields of immutable types (like scale
). So you are doing too much in your clone()
. Calling to super and Cloneable are also needed.
public Temperature clone()
{
return new Temperature(this.value, this.scale);
}
That's all you should need. The method you wrote simply assigned the fields of the calling object to themselves, and then calls itself. Eventually it overflows the stack with calls to itself without having really done anything.
If you want to use Object
's clone method you must implement Clonable interface.
According to documentation
Invoking Object's clone method on an instance that does not implement the Cloneable interface results in the exception CloneNotSupportedException being thrown.
public class Temperature implements Clonable // just this will work for your requirement
{
// other code
public Temperature clone() {
return super.clone() //this will server your purpose of cloning your temperature object.
}
}
But its not a good idea to follow this way. Its better to create a new instance from this object.
The reason for StackOverflowError is, you are calling your clone
method repeatedly, which will never return.
In many cases, clone()
is not the way to go. Obviously, if your instructor requires it than you have to write it and include implements Clonable
.
Otherwise it is often simpler to write a copy constructor:
public Temperature(Temperature original) { ... }
which builds a new Temperature
instance from an old Temperature
instance. That has the same effect as clone()
but can avoid some of the associated problems.
For extra credit, have you done enum
yet? If so then you might want to look at using an enum
here.
精彩评论