Why java.lang.Object can not be cloned? - java

When i try to clone a generic Object i get compile time error . why?
Object obj=new Object();
obj.clone(); // Here compile time error "The method clone() from the type Object is not visible"
Every class extends Object class and clone method is protected in Object class.
protected methods can be accessed in same package as well as by subclasses and all classes are child of java.lang.Object.

Because clone is protected in the Object class. It's not public.
The only way to get access to an object's clone() method is to know it has a compile-time type that has a public clone() method.

This will be the minimum to get clone working:
public class SubObj implements Cloneable {
public Object clone() { return super.clone(); }
}

Per the Java SE docs:
The class Object does not itself implement the interface Cloneable, so
calling the clone method on an object whose class is Object will
result in throwing an exception at run time.

protected fields can be accessed only from inside the same package, thus clone() method of Object class can be accessed only from any class that is located in java.lang package.

You must explicitely implements Cloneable interface.
see this thread which give explanations.

If you use Groovy so that you can bypass the java compilation error, you get this:
Exception in thread "main" java.lang.CloneNotSupportedException: java.lang.Object
at java.lang.Object.clone(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:86)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:230)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:912)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:756)
at org.codehaus.groovy.runtime.InvokerHelper.invokePojoMethod(InvokerHelper.java:766)
at org.codehaus.groovy.runtime.InvokerHelper.invokeMethod(InvokerHelper.java:754)
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.invokeMethodN(ScriptBytecodeAdapter.java:170)
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.invokeMethod0(ScriptBytecodeAdapter.java:198)
at regexTests.main(regexTests.groovy:19)
ERROR: JDWP Unable to get JNI 1.2 environment, jvm->GetEnv() return code = -2
JDWP exit error AGENT_ERROR_NO_JNI_ENV(183): [../../../src/share/back/util.c:820]
If you read the clone API (I will link it) it says that if the Interface isn't implemented, then calling *.clone() will throw a CloneNotSupportedException.
Link to the clone API for java.lang.Object
http://docs.oracle.com/javase/6/docs/api/java/lang/Object.html#clone%28%29
[EDIT]
The Original Question™ asked for why this method is visible in the way it is. This is because it only accessible to methods within the java.lang package. It isn't intended for a programmer to be able to clone an Object. Throwing a CloneNotSupportedException is exactly what you want to do if you don't want your OWN object cloned.

void method() {
Object obj=new Object(); //Object is a parent class, it's not inherit from any other class...
obj.clone(); // compile time error
}
We can't access the protected method of "Has A" relationship from different package, because your Class package is (com.xxx.yyy) and an Object class package is (java.lang) both the classes are in different package.
protected methods can be accessed in same package as well as by subclasses(IS A relationship)

I tried this code :
public final class User {
private String name;
private boolean isActive;
private String userId;
private Address address;
// can be constructed using this constructor ONLY !
public User(String name, boolean isActive, String userId, Address address) {
this.name = name;
this.isActive = isActive;
this.userId = userId;
this.address = address;
}
public String getName() {
return name;
}
public boolean isActive() {
return isActive;
}
public String getUserId() {
return userId;
}
public Address getAddress() {
return address;
}
protected Object cloneMe() throws CloneNotSupportedException {
return super.clone(); // throws CloneNotSupportedException
}
}
public class CloneNotSupportedException
extends Exception
Thrown to indicate that the clone method in class Object has been
called to clone an object, but that the object's class does not
implement the Cloneable interface. Applications that override the
clone method can also throw this exception to indicate that an object
could not or should not be cloned.
Object doesn't implement any interface and to make my User class work it must implement Cloneable

Object class clone() method has modified by protected access modifier in the API level. So we can't access it anywhere without inheritance. So before we invoke object class clone() method you need to implements Cloneable interface. Then Code will run at runtime properly. Otherwise it will generate CloneNotSupportedException at runtime.
/*Subclass is my implementing class */
public class SubClass implements Cloneable {
#Override
public SubClass clone() throws CloneNotSupportedException {
return (SubClass) super.clone();
}
}

import java.util.Scanner;
import java.util.jar.Attributes.Name;
import java.util.Arrays;
public class Main{
public class man{
protected void name() {
System.out.println("hei");
}
}
public class people extends man{
public int age;
public int getAge() {
name();
return age;
}
public void setAge(int age) {
this.age = age;
}
#Override
public String toString() {
return "people [age=" + age + "]";
}
public Object myclone() throws CloneNotSupportedException {
return this.clone();
}
}
public void test() throws CloneNotSupportedException {
people p1 = new people();
p1.setAge(10);
System.out.println(p1);
// NG:
people p2 = (people)p1.clone();
// Ok
people p3 = (people)p1.myclone();
p1.setAge(10);
System.out.println(p1);
System.out.println(p2);
}
public static void main(String args[]) throws CloneNotSupportedException{
new Main().test();
}
}
see the NG code and ok code.
// NG for:The method clone() from the type Object is not visible
people p2 = (people)p1.clone();
// Ok
people p3 = (people)p1.myclone();
why?
cause test() is not belong to the subclass.
so even though call clone() by peopel object p1,it is not the place of peopel object.
The myclone() is the exactly the place of people object.

Related

Cast an Object to its superclass in Java

Learning Java here and I try to cast on a super class and i cant access to subclass methods, is it possible, I am doing something wrong.
I have this:
public class Musician {
public String name;
public String surname;
}
public class Instrumentist extends Musician{
public String getInstrumento() {
return instrumento;
}
public void setInstrumento(String instrumento) {
this.instrumento = instrumento;
}
private String instrumento;
public Instrumentist(String nombre, String name, String surname){
this.name = nombre;
this.surname = surname;
}
}
public class Main {
public static void main(String[] args) {
Musician m = new Instrumentist("Antonio", "Vivaldi", "none");
System.out.println(m);
}
}
I know I can do Instrumentist i = new Instrumentist("Antonio", "Vivaldi", "none")
but then what is the purpose of Cast to superclass?
The concept is like this:
The superclass/interface provides general implementation or a contract. The subclass overrides/implements that contract.
To make sure that you can assign different implementations of that contract at runtime, you use reference of a Superclass and assign object of a subclass to it.
Musician m = new Instrumentist("Antonio", "Vivaldi", "none");
Here, with m, you can call methods defined in Musician class, but if your subclass has any other methods apart from those defined superclass, you can not access them using m. If subclass overrides any method, then even after using reference of superclass, say m, java would make sure that at runtime, overridden method in subclass is called.

Overriding Clone() method in Java when superclass is not Clonable

How to clone a Java object with the clone() method
I have a question regarding properly implementing the clone() method for a class in java.
I know that this is bad practice, but I need to know this for an exam..
In the above discussion they say to call super.clone() - but I don't udnerstand what happens if the super function doesn't implement Clonable.
For example, say I have a class X that extends Y. X implements Clonable and Y doesnl't. Y's clone() method should throw an Exception. Then what do we do in this case?
All the explanations I could find somehow assume that all superclasses implement Clonable, or at least that's what I understood..
EDIT:
Check out this code please:
public class Employee implements Cloneable {
private String name;
public Employee(String name) {
this.name = name;
}
public String getName() {
return name;
}
public Object clone()throws CloneNotSupportedException{
return (Employee)super.clone();
}
public static void main(String[] args) {
Employee emp = new Employee("Abhi");
try {
Employee emp2 = (Employee) emp.clone();
System.out.println(emp2.getName());
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
It is taken from here: https://www.javacodegeeks.com/2018/03/understanding-cloneable-interface-in-java.html
Similar code can be found in many tutorials.
Why can they use super.clone() when the superclass (which in this case is Object) does not implement Clonable - that would result in an Exception.
If you have this structure:
class Y {}
class X extends Y implements Cloneable {
#Override
public X clone() {
try {
return (X) super.clone();
} catch (CloneNotSupportedException e) {
throw new InternalError(e);
}
}
}
Then clone on instances of X will work fine.
It won't work on direct instances of Y, because they are not declared cloneable. But the Cloneable interface on X is an indicator to the mechanisms of the default clone() implementation that they should be made to work.
Alternatively
You could also have a non-Cloneable class with a working clone() method, as long as you didn't rely on the default implementation of clone().
For instance:
class Y {
#Override
public Y clone() {
// Don't call super.clone() because it will error
return new Y(...); // whatever parameters
}
}
However, with this mechanism, if you called super.clone() from a subclass of Y, you would get an instance of Y, which is probably not what you would want.
As others have pointed out, the Cloneable mechanism is awkward and confusing, and usually copying mechanisms using new are easier to work with.
The Cloneable-interface is generally regarded as broken (and won't be fixed). At the core, the argument revolves around the fact that clone() is a method defined on Object, instead of being a method of the interface Cloneable.
I would not recommend using it at all. A better solution would be to provide copy-constructors. If one does not have the capability to fully recreate a parent-class object, then cloning is impossible.
Refactoring the code provided would lead to a result similar to this:
public class Employee implements Cloneable {
private String name;
public Employee(String name) {
this.name = name;
}
public Employee(Employee that) {
this.name = that.name;
}
public static void main(String[] args) {
Employee emp = new Employee("Abhi");
Employee emp2 = new Employee(emp);
System.out.println(emp2.getName());
}
public String getName() {
return name;
}
}
A remark on your code:
public class Employee {
public Object clone()throws CloneNotSupportedException{
return (Employee)super.clone();
}
}
The type cast is superfluous since the methode returns an Object.

Java lazy instantation using inversion of control container

I have this container:
public class DIContainer {
protected static DIContainer instance;
protected Hashtable<Class<?>, Class<?>> classMap;
protected DIContainer(){
this.classMap = new Hashtable<Class<?>, Class<?>>();
}
public static DIContainer getInstance(){
if (DIContainer.instance == null)
DIContainer.instance = new DIContainer();
return DIContainer.instance;
}
public void regClass(Class<?> interf, Class<?> classToReg){
this.classMap.put(interf, classToReg);
}
public Object create(Class<?> interf, boolean lazy) throws Exception{
if(!this.classMap.containsKey(interf))
throw new Exception("No such class registered with "+interf.getName()+" interface");
else if(lazy == false)
return this.classMap.get(interf).newInstance();
else
return this.classMap.get(interf);
}
}
And I need to lazy create an object, if lazy creation option is chosen (so it would create some sub-object that would implement same interface). So when first method would be called for that sub-object, it would instantiate 'real' object. How could I do it as I don't know exact method that would be used? How can I check for if any method was called for that object?
Now I only tried this as lazy creation as you can see:
return this.classMap.get(interf);
But it gives me an error: java.lang.ClassCastException
Do I need some other method to check if any call was made to that sub-object, because after creation is done, I will be out of 'create' method and when method will be called I need to check it somehow?
Here are my test interface and it's implementation class:
public interface Interface1 {
public String getName();
public void setName(String name);
}
public class Class1 implements Interface1{
String name;
Class1(){}
#Override
public String getName() {
return name;
}
#Override
public void setName(String name) {
this.name = name;
}
}
And this is how I test it:
public class Main {
public static void main(String[] args) throws Exception{
DIContainer dic = DIContainer.getInstance();
dic.regClass(Interface1.class, Class1.class);
Interface1 t1 = (Interface1) dic.create(Interface1.class, true);
P.S. If I set lazy creation to false, then it works.
In your case, the line return this.classMap.get(interf); returns a Class object, which you previously put inside the map with the this.classMap.put(interf, classToReg) line. The Class object definitely cannot be cast to the Interface1 interface, as it does not implement it, which results in the ClassCastException.
What you actually need is to return a kind of a wrapper that implements the Interface1 interface and wraps the lazily instantiated class. When any of the interface's method is called, the wrapper instantiates the actual object and delegates the call.
If you want to lazy-init an arbitrary class, the most straight forward option would be to use Java's dynamic proxy.

Is it possible to use getters/setters of extended class in Java

I have the following
public abstract class MyData
{
private String sID;
public void setsID(String sID) {
this.sID= sID;
}
public String getsID() {
return sID;
}
}
This base class is being extended by 2 other classes
public class DataTypeOne extends MyData
{
private String sName;
public void setsName(String sName) {
this.sName= sName;
}
public String getsName() {
return sName;
}
}
public class DataTypeTwo extends MyData
{
private String sSummary;
public void setsSummary(String sSummary) {
this.sSummary= sSummary;
}
public String getsSummary() {
return sSummary;
}
}
I am initializing this class as follows
MyData oDataOne = new DataTypeOne();
MyData oDataTwo = new DataTypeTwo();
Reason for that is that I have a factory method which shall give me the class based on type (One or two)
With oDataOne & oDataTwo, I am able to access getsID() from the base class but not the getters & setters of the respective class.
How can I access those? I
You can't access a method that doesn't exist. All you've promised your Java compiler is that oDataOne and oDataTwo are MyData objects. Since the MyData class doesn't have the implementation-specific methods, you cannot ask Java to call those methods (since it doesn't think they exist).
If you want to access those methods, you need to either cast the object to a class that actually has the right methods, or you can add abstract method stubs to your base class, which will tell Java that those methods actually exist.
Type casting is simpler to write in the short term, but less clear, and you may run into more trouble down the road:
((DataTypeOne) oDataOne).getsName();
((DataTypeTwo) oDataOne).getsSummary(); // Throws ClassCastException!
Adding abstract stubs is more robust, but may not make sense if not all concrete subclasses should implement all abstract methods:
public abstract class MyData {
public abstract void setsName(String name);
public abstract String getsName();
public abstract void setsSummary(String summary);
public abstract String getsSummary();
}
public class DataTypeOne extends MyData {
public String getsName() {
// implement
}
public void setsName(String name) {
// implement
}
// Still have to implement these!!!
public String getsSummary() {
// raise an exception or something if appropriate
}
public void setsSummary(String summary) {
// raise an exception or something if appropriate
}
}
// Same for DataTypeTwo
Since you declared the variable as a MyData, you can only access the methods of MyData. You can get to the subclass methods by casting it to DataTypeOne or DataTypeTwo:
((DataTypeOne)oDataOne).getsName()
But you need to be sure it is of type DataTypeOne or you will get a ClassCastException
MyData oDataOne = new DataTypeOne();
this says, that your oDataOne object is of the type MyData. Even if it is created as a DataTypeOne, java can only be sure that it is defiantly a MyData instance.
If you are sure that the MyData instance is in reality also a DataTypeOne instance, you can cast and then access the DataTypeOne methods + the MyData methods.
To make sure that an object is of a specific type test:
if(oDataOne instanceOf DataTypeOne){
((DataTypeOne) oDataOne).getsName(); // this will return the Name if oDataOne is really of the type DataTypeOne
}
An object of type MyData has no knowledge of whether any other classes extends it or not, so there is no way to access members of those classes.
You will have to cast your object to the specific type to access the specific members.
If you find yourself in this situation, you can be pretty sure that your design is flawed. If you need to perform a specific action for each type of MyData extension, add a method, e.g specialAction() to the interface and hide the specifics in there. That eliminates the entire need to find out which subclass you are dealing with.

Cloning an Object in Java

I am trying to clone a DTO. I have taken a DTO Object as shown:
public class Employee implements Cloneable
{
String name;
String dept;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDept() {
return dept;
}
public void setDept(String dept) {
this.dept = dept;
}
}
But this line is giving me Error :
public class Test
{
public static void main(String args[]) {
Employee emp1 = new Employee();
emp1.setDept("10");
emp1.setName("Kiran");
Employee emp2 = (Employee) emp1.clone(); // This Line is giving error .
}
}
My query is that clone method is from Object, so why can't we use it directly like we do the `toString Method?
You have to override Object.clone(), which is protected. See the
java.lang.Cloneable and Object.clone() documentation.
More complete example here: How to implement Cloneable interface.
Unfortunately cloning in Java is broken. If you have an option, either try to define your own clone interface, one which actually has a clone method or use copy constructors to create copies of object.
Actually, never mind. You need to override the clone method in your class since its protected in java.lang.Object. Don't forget to remove the CloneNotSupportedException in the method signature, so that you don't have to handle it everywhere in your code.

Categories

Resources