Newbie: cloning a Number

P

Philipp

Hello
I have a class which take a Number as argument. I want to store it by
making a copy in a member of the class. I thought about using clone, but
my Eclipse IDE gives me an "Type mismatch: cannot convert from Object to
Number" error.
How should I do it? Thanks for your answers.
Phil

code:
public class ConvolutionMatrixSetting {
private Number [][] coefficients;
private Number scale;
private Number offset;
private int height;
private int width;
private String name;

public ConvolutionMatrixSetting(String name, Number[][] coefficients,
Number scale, Number offset){
this.name = name;

height = coefficients.length;
width = coefficients[0].length;

coefficients = new Number[height][width];
System.arraycopy(coefficients, 0, this.coefficients, 0, height);

this.scale = scale.clone(); // DOES NOT WORK
this.offset = offset.clone(); // DOES NOT WORK
}
}
 
A

Andreas Leitgeb

Philipp said:
this.scale = scale.clone(); // DOES NOT WORK
this.offset = offset.clone(); // DOES NOT WORK

clone() itself is inherited from Object, and returns "Object".
Of course these objects are really Numbers, but the java-compiler
doesn't know.

In that context it seems safe to just use casts:
this.scale = (Number)scale.clone();
this.offset = (Number)offset.clone();

If you're thoroughly paranoid, add
"if (scale instanceof Number)"
before each of these two lines and
some error-handling "else" branch
after each. :)
 
P

Philipp

Andreas said:
clone() itself is inherited from Object, and returns "Object".
Of course these objects are really Numbers, but the java-compiler
doesn't know.

In that context it seems safe to just use casts:
this.scale = (Number)scale.clone();
this.offset = (Number)offset.clone();

Hello and thanks for your answer.
With the above code I get a "The method clone() from the type Object is
not visible" error.
What I can I do about that?
Phil
 
P

Patricia Shanahan

Philipp said:
Hello
I have a class which take a Number as argument. I want to store it by
making a copy in a member of the class. I thought about using clone, but
my Eclipse IDE gives me an "Type mismatch: cannot convert from Object to
Number" error.
How should I do it? Thanks for your answers.
Phil

Number does not itself implement Cloneable, and immediately extends
Object, so I don't think it can be cloned.

Are you sure you need to clone the Number, rather than just keeping a
reference? There are a couple of new subclasses, AtomicInteger and
AtomicLong, but most Number subclasses have immutable objects.

Patricia
 
P

Philipp

Patricia said:
Number does not itself implement Cloneable, and immediately extends
Object, so I don't think it can be cloned.

Are you sure you need to clone the Number, rather than just keeping a
reference? There are a couple of new subclasses, AtomicInteger and
AtomicLong, but most Number subclasses have immutable objects.

Hello
Yes if subclasses of Number are immutable it really doesn't make much
sense to have a clone methode.

Thanks for that clarification.

I'm still surprised that it is not provided, even just for completness
(as well as for String, but there you have a copy ctor).
Is clone evil?

Phil
 
P

Patricia Shanahan

Philipp said:
Hello
Yes if subclasses of Number are immutable it really doesn't make much
sense to have a clone methode.

Thanks for that clarification.

I'm still surprised that it is not provided, even just for completness
(as well as for String, but there you have a copy ctor).
Is clone evil?

Phil

I don't understand clone's attraction for a class such as String, a
final class with immutable instances.

Perhaps you could explain why you would prefer a clone to a reference to
the original String?

Patricia
 
P

Philipp

Patricia said:
I don't understand clone's attraction for a class such as String, a
final class with immutable instances.

Perhaps you could explain why you would prefer a clone to a reference to
the original String?

Sorry I did'nt know that String was immutable. How do you tell from the
JavaDoc if a class is immutable?
I think this is vital as you have to know if keeping a reference is
enough to assure the persistence of a value or if you have to make some
sort of copy.

I understand now that when you write
String a = "hello";
a = "world";
you are actually creating a new String in memory and not re-using (ie
assigning to) the old memory (correct?)

Phil
 
P

Patricia Shanahan

Philipp said:
Sorry I did'nt know that String was immutable. How do you tell from the
JavaDoc if a class is immutable?

Unfortunately, there is no standard tag. However, the second paragraph
in the String API documentation says:

"Strings are constant; their values cannot be changed after they are
created. String buffers support mutable strings. Because String objects
are immutable they can be shared."

Also, there are no methods that change the value of a String.
I think this is vital as you have to know if keeping a reference is
enough to assure the persistence of a value or if you have to make some
sort of copy.
Agreed.


I understand now that when you write
String a = "hello";
a = "world";
you are actually creating a new String in memory and not re-using (ie
assigning to) the old memory (correct?)

Yes. There is one object "hello". "world" is an entirely different
object. The reference a initially points to the object "hello", and then
is modified to point to the object "world".

Patricia
 
A

Andreas Leitgeb

Patricia Shanahan said:
I don't understand clone's attraction for a class such as String, a
final class with immutable instances.

I think, String was just used for comparision:
It *can* be indirectly cloned.
But that is just because it is not abstract (nor an interface).

Number is not final, and thus not guaranteed immutable.
So I do understand the wish for Number being cloneable.

Specify verbally in the docs that only either immutable,
or unshared instances shall be passed to your method.
 
P

Patricia Shanahan

Andreas said:
I think, String was just used for comparision:
It *can* be indirectly cloned.
But that is just because it is not abstract (nor an interface).

Number is not final, and thus not guaranteed immutable.
So I do understand the wish for Number being cloneable.

Specify verbally in the docs that only either immutable,
or unshared instances shall be passed to your method.

In Number's case the original API classes extending it all did have
immutable instances, but there are two problems with depending on that:

1. As you say, Number is not final, so there could be implementations
outside the API.

2. The new AtomicInteger and AtomicLong are definitely not immutable,
but extend Number.

AtomicInt and AtomicLong do not themselves implement Cloneable. That
does make some sense. By definition, they are intended for shared data
without explicit synchronization. Making a copy is rather problematic,
because another thread could be changing the value as you copy.

Maybe it's time to look at the problem one level up? Why is the Number
copy being made? Does it make sense for all Number implementations?

Patricia
 
A

Andreas Leitgeb

Making a copy is rather problematic,
because another thread could be changing the value as you copy.

Isn't it the whole point of these Atomic* classes, that you
*can* retrieve the value atomically?

So you could also clone it (theoretically), just like you
can create a new Abstract*, with original.get() as argument.
If something else happens concurrently, you either get the
old value or the new value, but guaranteed no mixture.
 
E

Eric Sosman

Patricia said:
Number does not itself implement Cloneable, and immediately extends
Object, so I don't think it can be cloned.

Are you sure you need to clone the Number, rather than just keeping a
reference? There are a couple of new subclasses, AtomicInteger and
AtomicLong, but most Number subclasses have immutable objects.

Two notable exceptions (I'd never have noticed had not Joshua
Bloch pointed it out) are BigDecimal and BigInteger. The classes
in java.math are immutable, but they are non-final classes and so
can be extended, and the unknown subclasses could be mutable.
 
P

Patricia Shanahan

Eric said:
Two notable exceptions (I'd never have noticed had not Joshua
Bloch pointed it out) are BigDecimal and BigInteger. The classes
in java.math are immutable, but they are non-final classes and so
can be extended, and the unknown subclasses could be mutable.

Yup, you can't resolve the issue just by instanceof testing for those
classes.

Patricia
 
E

Eric Sosman

Philipp said:
Sorry I did'nt know that String was immutable. How do you tell from the
JavaDoc if a class is immutable?

By reading where it says "Strings are constant; their values
cannot be changed after they are created. [...] Because String
objects are immutable [...]"

However:

"Immutable" is a slightly fuzzy concept. We say that a class
is "immutable" if the value of an instance cannot be changed after
the instance is constructed. Well, what exactly do we mean by the
"value" of an object? Here's a class:

public class Immutable {
private final Object value;
public Immutable(Object value) {
this.value = value;
}
public String toString() {
return String.valueOf(value);
}
}

Is an Immutable instance "immutable" or "mutable?" It encapsulates
an Object reference, and that reference can't change, so in that
sense it's "immutable." But if I write

StringBuffer sb = new StringBuffer("Hello");
Immutable im = new Immutable(sb);
System.out.println(im);
sb.append(", world!");
System.out.println(im);

have I changed the "value" of the Immutable instance? Maybe yes,
maybe no. The two lines of printed output are clearly different,
so "something about" the Immutable instance has changed, even though
not a single bit of the memory devoted to the instance has flipped.
The notion of "immutability" depends, really, on the "purpose" of
the class -- and "purpose" is a tricky notion to pin down.

Even the classes that most people will call "immutable" usually
aren't, if sufficiently drastic steps are taken. The canonical
example of an "immutable" class is surely String, yet code has been
posted here that uses reflection to get at and modify the char[]
underlying the String. If the same String object prints as "Hello"
once and as "world" later, has its value changed? Most people would
say that it has -- and so we modify "immutable" to be "immutable
except under special circumstances," and "special" is yet another
hard-to-define word.
 
D

Daniel Pitts

Eric said:
Philipp said:
Sorry I did'nt know that String was immutable. How do you tell from the
JavaDoc if a class is immutable?

By reading where it says "Strings are constant; their values
cannot be changed after they are created. [...] Because String
objects are immutable [...]"

However:

"Immutable" is a slightly fuzzy concept. We say that a class
is "immutable" if the value of an instance cannot be changed after
the instance is constructed. Well, what exactly do we mean by the
"value" of an object? Here's a class:

public class Immutable {
private final Object value;
public Immutable(Object value) {
this.value = value;
}
public String toString() {
return String.valueOf(value);
}
}

Is an Immutable instance "immutable" or "mutable?" It encapsulates
an Object reference, and that reference can't change, so in that
sense it's "immutable." But if I write

StringBuffer sb = new StringBuffer("Hello");
Immutable im = new Immutable(sb);
System.out.println(im);
sb.append(", world!");
System.out.println(im);

have I changed the "value" of the Immutable instance? Maybe yes,
maybe no. The two lines of printed output are clearly different,
so "something about" the Immutable instance has changed, even though
not a single bit of the memory devoted to the instance has flipped.
The notion of "immutability" depends, really, on the "purpose" of
the class -- and "purpose" is a tricky notion to pin down.

Even the classes that most people will call "immutable" usually
aren't, if sufficiently drastic steps are taken. The canonical
example of an "immutable" class is surely String, yet code has been
posted here that uses reflection to get at and modify the char[]
underlying the String. If the same String object prints as "Hello"
once and as "world" later, has its value changed? Most people would
say that it has -- and so we modify "immutable" to be "immutable
except under special circumstances," and "special" is yet another
hard-to-define word.

I would consider an object to be immutable if no behaviour could change
its semantic value after instantiation.

class MyClass {
private final char[] array = new char[10];
public char[] getArray() {
return array;
}
}

This is a simple case where there are only constant references, but the
class is mutable. Often times it takes special care to ensure that a
class is immutable (cloning returned objects that are mutable, wrapping
collections in unmodifiable collection wrappers, etc...)


class MyImmutableClass {
private final char[] array = {'T', 'w', 'i', 's', 't', 'e', 'd', '
', 's','u', 'c', 'k', 's'};
public char[] getArray() {
return (char[])array.clone();
}
}

This class is immutable.

Hope this helps

- Daniel.
 
P

Philipp

Maybe it's time to look at the problem one level up? Why is the Number
copy being made? Does it make sense for all Number implementations?

OK from the problem perspective:

My application needs some parameters (Number). I have some presets value
for these params which I want to store in a class called
ConvolutionMatrixSetting. I want to be sure that once I have constructed
an instance of this class, each time I call it (with some getter) I am
sure to get back the original values with which it was constructed.
This is the expected behavior and should in no way depend on what has
happened outside the setting class.

How should this be done?

PS: Thanks all for your input on the /immutable/ subject.
 
A

Andreas Leitgeb

Philipp said:
My application needs some parameters (Number).

Number itself allows only conversion to any of the
standard types (int,long,float,double,...).

So, if you make use of the value inside your class,
you already need to know whether you use it as a
floating-point or integer number.
So, you could just as well use double or long.
 
P

Philipp

Andreas said:
So, you could just as well use double or long.

Yes this is correct.
I just thought that this was the whole purpose of a "Number" class. ie
not needing to say if it's actually an integer or a double, but leaving
this to when real calculation is done.

Also my parameters are displayed in JFormattedTextFields which I would
like not to display Integers and Double the same way (with or witout
fraction digits). So keeping this info seemed important to me.

From my C++ background I would have implemented the standard math
operators (+ - * /) on Number such that the polymorphism is used (ie if
Number*Number is actually Integer*Integer: do integer math. If it's
Double*Integer do double math). But this does not seem to be the purpose
of the Number class in Java.
(what's it's purpose actually?)

Best regards
Phil
 
P

Patricia Shanahan

Philipp said:
OK from the problem perspective:

My application needs some parameters (Number). I have some presets value
for these params which I want to store in a class called
ConvolutionMatrixSetting. I want to be sure that once I have constructed
an instance of this class, each time I call it (with some getter) I am
sure to get back the original values with which it was constructed.
This is the expected behavior and should in no way depend on what has
happened outside the setting class.

How should this be done?

PS: Thanks all for your input on the /immutable/ subject.

What are you ultimately going to do with the Number? Usually one does
arithmetic using the elements of a convolution matrix, but Number is not
an arithmetic type, and there is no user-defined operator overloading,
so that is not practical.

Patricia
 
E

Eric Sosman

Daniel said:
I would consider an object to be immutable if no behaviour could change
its semantic value after instantiation.

Now you're stuck with defining "semantic value" in terms
a compiler can recognize. Good luck ...

As for behavior: Can you even define *that* precisely?
For example (chosen with malice aforethought): Is the ability
of an object to suspend a thread part of its behavior? That
is, is the state of an object's lock part of its behavior? If
so, *all* objects are mutable, and trivially so: All you need
do is synchronize on the object, and bang! its behavior w.r.t.
other attempted synchronizations is altered. Its state has been
changed, has been "mutated," and so it is "mutable."

Well, you might argue that the lock does not contribute to
the "behavior" of an object. That seems to me an untenable
position: If thread T1 can synchronize on an object and then
twiddle its thumbs for twenty minutes, surely that state of
affairs can influence the behavior of thread T2 (to wit, by
inhibiting T2's forward progress for some fraction of twenty
minutes). If T2 prints the time of day before and after a
stretch of code that synchronizes on the object, surely T1's
holding of the lock influences T2's behavior, does it not? From
the perspective of any thread attempting to synchronize, the
object's locked or unlocked state changes its observable behavior.

I'll repeat my earlier assertion: "``Immutable'' is a slightly
fuzzy concept." The harder you try to pin it down, the fuzzier it
becomes. It squirms off the microscope slide, it Heisenbergs
itself away to Never-Never Land, and eventually it inhabits the
same realm as Potter Stewart's famous opinion: "I shall not attempt
to define [obscenity] but I know it when I see it." Legal eagles
may be comfortable with such non-answers, but people who realize
that they must predictably arrive at ONE or ZERO are not.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,598
Members
45,152
Latest member
LorettaGur
Top