I know that using this cloning mechanism is not a good idea (since it is 'broken' as some authors suggest), although I need help understanding how it works. We're given the following class hierarchy:
class N implements Cloneable{
protected int num;
public N clone() throws CloneNotSupportedException{
return (N)super.clone();
}
}
class M extends N{
protected String str;
public M clone() throws CloneNotSupportedException{
M obj = (M)super.clone();
obj.setString(new String(this.str));
return obj;
}
void setString(String str){
this.str = str;
}
}
Since N extends Object, how does the super.clone() return an instance of N? super.clone() is actually Object.clone() which returns a reference to an object of class Object. Why are we then able to cast it to N? N has a member num that is not in the class Object. How does the default behavior actually manage to automatically clone this variable (since it has no record of it in class Object)?
Also, the same goes for M. In M.clone() we're casting an object from class N (returned by super.clone()) to an object of class M. I know that all of this is valid, yet I do not understand why.
Object#clone is a native method that makes a low-level binary copy of your object, thus producing another instance of the same class. Therefore it is safe to downcast.
Note that this is the only way to have a polymorphic cloning method.
Technically, Object.clone() is a native method:
protected native Object clone() throws CloneNotSupportedException;
And the JVM internally knows how big the current object is, and what the type of the object is. So, it can create the appropriate object as a bit-wise copy and return a reference to it.
Since N extends Object, how does the super.clone() return an
instance of N?
super.clone() is actually Object.clone() which returns a reference
to an object of class Object. Why are we then able to cast it to N?
N has a member num that is not in the class Object. How does the
default behavior actually manage to automatically clone this
variable (since it has no record of it in class Object)?
Answers :
At runtime, you are inside an instance of N class calling its parent clone method. Consider it the exact same thing as if you had overrided it in your N class. The Object class is a native, and abstract object. When you call N.toString() in fact you call the first toString method the JVM finds in N's hierarchy.
Same here, remember you are in an instance of N class.
it does not : How do I copy an object in Java?
You can also use the XStream object to clone your objects, like this :
public static <T> T cloneObject(
T object) {
XStream xstream = new XStream();
return (T) xstream.fromXML(xstream.toXML(object));
}
Related
I'm interested to know that, is it really possible to create an object reference for a java class without invoking any of it's constructors? If yes, how?
Definitely a bad idea, but you could use the sun.misc.Unsafe class to allocate an instance:
public static class TestClass {
int field = 1;
}
public static void main(String[] args) throws Exception {
Constructor<Unsafe> constructor = Unsafe.class.getDeclaredConstructor();
constructor.setAccessible(true);
Unsafe unsafe = constructor.newInstance();
TestClass test = (TestClass) unsafe.allocateInstance(TestClass.class);
System.out.println(test.field);
System.out.println(new TestClass().field);
}
Output:
0
1
It is possible by using JNI.
http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/functions.html
Object Operations
AllocObject
jobject AllocObject(JNIEnv *env, jclass clazz);
Allocates a new Java object without invoking any of the constructors for the object. Returns a reference to the object.
The clazz argument must not refer to an array class.
It is hard to find any relevant usage of it. I would not use it but it is still an answer to the question.
The only way i can think of is using the clone() method
Object objectA = objectB.clone();
Now objectA.clone() != objectA and objectA and objectB point to two different places in memory so technically you create an object without calling its constructor.
Not possible. Every class has a default constructor that calls its parent constructor super() which boils down to Java's Object Class.
class One {
public void doThing(One o) {System.out.println("One");}
}
class Two extends One{
public void doThing(Two t) {System.out.println("Two");}
}
public class Ugly {
public static void main(String[] args) {
Two t = new Two();
One o = t;
o.doThing(new Two());
}
}
Result : One
class One {
public void doThing(One o) {System.out.println("One");}
}
class Two extends One{
public void doThing(Two t) {System.out.println("Two");}
}
public class Ugly {
public static void main(String[] args) {
Two t = new Two();
One o = t;
t.doThing(new Two());
}
}
Result : Two
I know that at runtime, even though the object reference is of the super class type, the actual object type will be known and the actual object's method will be called. But if that is the case, then on runtime the doThing(Two t) method should be called but instead the super class method doThing(One o) is called. I would be glad if somebody explained it
In the second piece of code it prints "Two".
Question : when calling from the super class reference it is calling the doThing(One o)
when calling from the sub class reference it is calling the doThing(Two o)
NOTE: I know that i am over loading and not over riding. i have edited my question for better clarity.
The method doThing() have different method signature in One and Two.
One.doThing(One one)
Two.doThing(Two two)
Since, the signature isn't matched, Two.doThing(Two) doesn't Override One.doThing(One) and since o is of type One, One.doThing() is called.
Also to be noted that One.doThing(One) can take instance of Two as an argument for One.doThing(One) as Two extends One.
Basically, "#nachokk - You are Overloading, not Overriding"
In first scenario, when you did
Two t = new Two();
One o = t;
o.doThing(new Two());
So, o is an instance of One and Two.doThing(Two) isn't available to o thus calls One.doThing(One)
In second scenario,
Two t = new Two();
One o = t;
t.doThing(new Two());
t is an instance of Two and thus Two.doThing(Two) is called.
The excelent book SCJP for Java 6 states:
If a method is overridden but you use a polymorphic (supertype)
reference to refer to the subtype object with the overriding method,
the compiler assumes you’re calling the supertype version of the
method.
So basically with using supertype for reference you're telling compiler to use supertype method.
You are just overloading,as you said
Two t = new Two();
One o = t;
o.doThing(new Two());
Even though the actual object at runtime is a Two object and not a One object, the
choice of which overloaded method to call (in other words, the signature of the
method) is NOT dynamically decided at runtime. Just remember, the reference
type (not the object type) determines which overloaded method is invoked!
When you call doThing() method with Two object argument,you will invoke One super class doThing() method.The doThing() method needs a One object, and Two IS-A One.
So, in this case, the compiler widens the Two reference to a One object, and
the invocation succeeds. The key point here is that reference widening depends on
inheritance, in other words the IS-A test.
This is something trick question
Your statment
One o = t;
I think , you are assuming that class One 'o' is equal to Class Two 't', which is not actually equal to class Two 't'
as Class Two 't' is inherited from Class One, so it will assign the base class One in your case,
So variable 't' is reference of the class One and hence will call the method of class One.
More over you create one more class named as ClassC class and try to set your statement
ClassC c= new ClassC () and then
One o = c;
You will get an error... hope the answer your question.
At the compile time the compiler searches the class One for the method doThing(Two t) but since there isn't a method with that signature it starts widening its search and finds doThing(One o). Then it holds the binary file with the descriptor one parameter whose type is One : void. At runtime since the object invoking the method is of type Two, in class Two it looks for the method that matches the descriptor and doesn't search for the method doThing that accepts an object of Two as it considers the descriptor in the binary file it links the call to the method doThing(One o).
the java specs was of great help explaining this. here is the link
I am looking at the Interface chapter provided on the Java website
Using Interface as a type
So my understanding was that the whole point of interface is that it is like a class but it's not possible to form objects from it, but this page says how to use interface as a data type. the line Relatable obj1 = (Relatable)object1; seems to create an object of type Relatable which is an interface. Although I must say that the new keyword has not been used here, thus not really creating a reference to an object of type Relatable. Is that really the cause for this line NOT creating an object of type Relatable?
Again, it further says
If you make a point of implementing Relatable in a wide variety of
classes, the objects instantiated from any of those classes can be
compared with the findLargest() method—provided that both objects are
of the same class.
What does this mean? Does this mean anything that implements Relatable can call findLargest()? If it's so, why does it say provided that both objects are of the same class?
----- EDIT -----
From the previous chapters of this tutorial:
Definition of relatable:
public interface Relatable {
// this (object calling isLargerThan)
// and other must be instances of
// the same class returns 1, 0, -1
// if this is greater // than, equal
// to, or less than other
public int isLargerThan(Relatable other);
}
Using relatable as a type:
public Object findLargest(Object object1, Object object2) {
Relatable obj1 = (Relatable)object1;
Relatable obj2 = (Relatable)object2;
if ((obj1).isLargerThan(obj2) > 0)
return object1;
else
return object2;
}
----- EDIT 2 -----
In the chapter on anonymous classes, it does this:
public class HelloWorldAnonymousClasses {
interface HelloWorld {
public void greet();
public void greetSomeone(String someone);
}
.
.
.
HelloWorld englishGreeting = new EnglishGreeting();
HelloWorld frenchGreeting = new HelloWorld() {
String name = "tout le monde";
public void greet() {
greetSomeone("tout le monde");
}
public void greetSomeone(String someone) {
name = someone;
System.out.println("Salut " + name);
}
};
So how does this work?
the line Relatable obj1 = (Relatable)object1; seems to create an object of type Relatable
No. This line creates a reference (obj1) of type Relatable and assigns it to object1. In order for this to work, object1 has to be cast to the (interface) type Relatable.
No new objects are being created here.
Does this mean anything that implements Relatable can call findLargest()?
Yes.
If it's so, why does it say provided that both objects are of the same class?
It has to do with the implementation of isLargerThan(). Since any class implementing the Relatable interface can't know anything about other classes implementing it, they can't do meaningful comparisons with other classes. Therefore, in order for this to work, both objects need to be of the same class.
Response to EDIT 2
So how does this work?
Instead of first defining a class and then creating an instance of it, as in the case with the EnglishGreeting, the frenchGreeting is created on the fly. What happens under the cover is that a new class implementing HelloWorld is created, just like in the english case, only this time it is anonymous (you never get to give it a name). It is just a convenience shortcut for those times when you need a one-time implementation of an interface.
Interface types belong to the category of reference types in java. You can never instantiate an interface, but it can be assigned references to any of the objects of classes which implement it:
A variable whose declared type is an interface type may have as its
value a reference to any instance of a class which implements the
specified interface.
Interfaces are like behaviors. If a class happens to implement an interface, lets say Serializable, this adds a behavior to the class, which is, the class can be serialized.
This helps you introduce abstraction in your code. For example lets assume that you need a method in one of your utility classes which will be responsible for the actual job of serialization. Without interfaces you will end up writing a lot of methods, one for each object type that you want to serialize. Now imagine if you asked each of those objects to take care of their serialization themselves (by implementing a serialize method declared in the interface they implemented). With such implementation you need to write only one utility method for serialization. This method can take an argument of Serializable type, and instances of any class implementing this interface can be passed to the method. Now within the method you only need to invoke the serialize method on the interface variable. At runtime this will result in actual object's serialize method getting invoked.
Hope I was able to keep it simple.
Interface in Java is a mutual structure for classes that implement the interface, so the classes benefit from the methods/other member of that interface in their own way, which is called polymophism,
interface A
{
// method header only declared here, so implementation can vary between classes
public int foo();
}
class B implements A
{
public override String foo()
{
return "Class B";
}
}
class C implements A
{
public override String foo()
{
return "Class C";
}
}
so you can call foo() both from class B and C but they will react differently since they implement that method in their own way
An interface is just a class that defines the behaviour of an object, but not the underlaying implementation of it.
By making Relatable obj1 = (Relatable)object1; you are just casting the object1 to a Relatable type, and therefore you can call any of the methods defined in the Relatable interface
To your first question about Relatable obj1 = (Relatable)object1;:
A simple Relatable obj1; will not create an instance of Relatable, but specifies that any object assigned to it must be of a type implementing the Relatable-interface.
Therefore any object that is to be cast, must be of a type implementing the Relatable-interface.
The following snippet gives output as
Sup.field=0, Sup.getField()=1
I do not understand why Sup.getField() does not get 0 instead?
class Super {
public int field = 0;
public int getField(){return field;}
}
class Sub extends Super {
public int field = 1;
public int getField() {return field;}
public int get SuperField() { return super.field;}
}
public class FieldAccess{
public static void main(String[] args){
Super Sup = new Sub();
System.out.println("Sup.field ="+Sup.field + ",Sup.getField()"+Sup.getField());
}
}
Instance variables are not overridden ..they are merely hidden. Referring to the super.field refers to the actual field in the super class based on reference.
Methods are overridden and the call is made based on the object type at runtime.
All methods in java are virtual (c# term) or polymorphic by default and that's what you are seeing (the class fields are not).
When you call sup.field, it accesses field field in class Super but when you call getField() it calls the getField() method in class Sub because the instance is of type Sub.
This page has a good definition and some examples of polymorphism.
This is because,
Super Sup = new Sub();
This means that the object holds instance of the derived class object. That means, in the object memory the value of field is 1 and not 0.
So, when you run
Sup.getfield()
it runs the method of the derived class which resides in the memory that is tagged as memory for the Super class.
So, Its the difference in what it is and what it seems like.
What you are witnessing is the effect of method overriding (not to be confused with method overloading).
Even though the reference type is of type Super(), the actual method to call is resolved when the program is executing (runtime polymorphism), and because the getField() method is overridden by the subclass, that is what gets called and hence returns the value in the subtype. If you want 0 in both cases, change your instantiation to Super Sup = new Sub();
its easier to explain in code so here
Object anObj;
anObj = new MyObj();
anObj = new Rectangle();
anObj.clone();//this doesnt exist because its on the root Object class
what can i use instead of the Object.clone() method in this example?
----------------------- extra info ------------------------------
I have added extra info but it seems to have gone in the middle of all the answers, so here it is again so it can be read.
Hi all these are all really helpful on topic of cloning or copying, which i now need to think about. but they dont help with the initial question. maybe more info from me will help you understand what im after.
I am overriding the clone for each of my objects and adding all the other clone and copy methods needed to completely clone the object, this includes adding a custom method to copy a bufferedimage.
ie:-
public Object clone() {//i copied from 'thelost's answer
try {
CloningExample copy = (CloningExample)super.clone();
copy.names = (LinkedList)names.clone();
return copy;
} catch (CloneNotSupportedException e) {
return null;
}
}
but i have one variable in my class that is an Object but because it hold various other objects of different types, each of my types will have a clone method, but short of checking if its each of my types and then calling clone() on my type, which would be very long as i have many types, i cannot see how to copy or clone the object easily. is there a way os should i just write a static method like this?
static findTypeAndCopy(Object thisobj){
if(thisobj==null)
return null;
if(thisobj instanceOf MyObj1){
return ((MyObj1)thisobj).clone();
}else if(thisobj instanceOf MyObj2){
return ((MyObj2)thisobj).clone();
...
etc
}
???
You seem to have realized that Cloneable in Java is broken.
Here are some quotes from an interview with Josh Bloch, author of Effective Java 2nd Edition:
If you've read the item about cloning in my book, especially if you read between the lines, you will know that I think clone is deeply broken. There are a few design flaws, the biggest of which is that the Cloneable interface does not have a clone method. And that means it simply doesn't work: making something Cloneable doesn't say anything about what you can do with it. Instead, it says something about what it can do internally. It says that if by calling super.clone repeatedly it ends up calling Object's clone method, this method will return a field copy of the original.
But it doesn't say anything about what you can do with an object that implements the Cloneable interface, which means that you can't do a polymorphic clone operation.
Here are some quotes from the book, Item 11: Override clone judiciously:
[...] you are better off providing alternative means of object copying, or simply not providing the capability.
[...] A fine approach to object copying is to provide copy constructor or copy factory. A copy constructor is simply a constructor that takes a single argument whose type is the class containing the constructor:
public Yum(Yum yum);
A copy factory is the static factory analog of a copy constructor:
public static Yum newInstance(Yum yum);
Related questions
Why is the clone() method protected in java.lang.Object?
Why people are so afraid of using clone() (on collection and JDK classes) ?
How to properly override clone method?
clone() vs copy constructor vs factory method??
Alternative: Cloneable 2.0
If you really insist on having a Cloneable-like functionality that isn't broken, you can write something like this (generified for extra jazz):
public class DupableExample {
interface Dupable<T> {
T dup();
}
static class Sheep implements Dupable<Sheep> {
Sheep(Sheep sheep) { }
#Override public Sheep dup() {
return new Sheep(this);
}
}
public static void main(String[] args) {
Dupable<?> dupable = new Sheep(null);
System.out.println(dupable);
System.out.println(dupable.dup());
// no cast needed
Sheep dolly2 = new Sheep(null).dup();
}
}
The output should be something like this (as seen on ideone.com):
DupableExample$Sheep#{some hexadecimal code}
DupableExample$Sheep#{a different hexadecimal code, in all likelyhood}
So now given any Dupable<T>, you can invoke T dup() on it to get what you expect is a duplicate copy.
This is just a proof-of-concept: in actual implementation, your copy constructor/copy factory/whatever copy mechanism will actually have the copying logic implemented, and Dupable<T> would be a public top-level interface.
The best idea is to avoid cloning, as it is broken.
Cloneable interface doesn't have method clone. Method clone is defined as protected in Object class. So to call clone you need to know the type of object to have access to clone.
Better idea is either copy constructor (as Bloch recommends) or serialization and deserialization (via XML for example).
Maybe you can gain access to clone with reflection, but I'm not sure. And I discourage it.
You can't know for sure that a class has the capacity to clone because clone() is a method from Object. The best you can do is to check if the class is Cloneable. Usually when a class is Cloneable it means that the developer overrode the clone() method.
But even so, Object can't call this method.
There is the reflection solution. But as the doc says :
Even if the clone method is invoked reflectively, there is no guarantee that it will succeed.
You can read documentation here, and there is a statement from Josh Bloch on this class (last paragraph).
You could check whether it implements the Cloneable interface and if it does then use the clone method.
And here is and example on how to implement it yourself.
As others have said: Clonable is broken and you should consider other options such as copy constructors. Having said that, here is a solution that should work if you really must use clone():
Object clone = null;
if(anObj instanceof Clonable) {
Method cloneMethod = anObj.getClass().getMethod("clone");
/*
* TODO: Handle the case where an object is cloneable but
* does not have a public clone() method.
*/
clone = cloneMethod.invoke(anObj);
} else {
throw new RuntimeException("can't clone object");
}
Or you could use reflection to clone the object field by field, if it does not implement clone()... Get all fields, copy the values to the new object. But this is tricky, if the object has no no-arg constructor.
interface PublicCloneable extends Cloneable{
public Object clone();
}
class MyObject implements PublicCloneable {
public Object clone() {
return super.clone();
}
}
class MainObject {
public static void main(String[] params) {
Object m = new MyObject();
if (m instanceof PublicCloneable) {
Object c = m.clone();
}
}
}