How to clone a object to a object of Object class? - java

As I have learned, Object class is a top level class and it is a parent of all classes. If we do not know a type of class at compile time, we can assign it to a object of Object class.
I am trying to clone a object to object of a Object class. Also trying to get the object from HashMap which is already instantiated. I am having problem in doing this. Can you figure out it and explain the right ways of doing it? I have commented in which lines I get compile time error. My main doubts are:
If a parent class' object can be used for cloning, then it must work with Object class too as it is top level class.
And how to access object from map and use it for method call and cloning.
Code:
import java.util.HashMap;
import java.util.Map;
class Sample {
public void call(){
}
}
class Question extends Sample implements Cloneable {
#Override
public void call(){
System.out.println("hello");
}
#Override
public Object clone()throws CloneNotSupportedException{
return super.clone();
}
public static void main(String args[]) throws CloneNotSupportedException{
Map<Character,Object> map=new HashMap();
Question s=new Question();
Sample q=new Question();
Sample cl=(Question)s.clone();
Object ob=(Question)s.clone();//no compile time error
map.put('o',s);
s.call();//hello
q.call();//hello
cl.call();/hello
ob.call();//Compile time error: cannot find symbol call
map.get('o').call();//Compile time error: cannot find symbol call
Object obj=(Question) (map.get('o')).clone();// Compile time error: clone has protected access in Object
}
}

The following line can be simplified
Object ob=(Question)s.clone();//no compile time error
// the cast is unnecessary:
Object ob= s.clone();
But like you said, the ob will still contain a Question object. The problem is that once you start using this ob reference, java just knows it contains a value of Object, or a subclass of it. So for java ob could be a Number or a String or an Airplane.
Object ob = "airplane";
Once it gets to the line ob.call() it refuses. Because it's not sure that the ob object has a call method. For example, if it was a String or a Number it would be impossible.
For this reason you have to perform a simple cast first:
((Question)ob).call();
// or
((Sample)ob).call();
Just let java know that it's an object with a call method.
The map#call issue has the same reasoning:
map.get('o').call();
//could be any of these
((Sample)map.get('o')).call();
((Question)map.get('o')).call();
But the last problem is more tricky. Actually a lot gets clear when you split up your statement in multiple lines:
Object obj=(Question) (map.get('o')).clone();
// would be the same like writing:
Object value = map.get('o');
Object value2 = value.clone();
Object obj = (Question) value2; // The (Question) cast is actually unnecessary.
The problem is in the value.clone() step. It is true that the Object class has a clone method, but it's marked as protected whereas the clone methods in your Question and Sample classes are public.
So in short Object#clone is not accessible ; Sample#clone and Question#clone are accessible.
// so you want this:
Object value = map.get('o');
Object value2 = ((Question)value).clone(); // add a cast here
Object obj = value2;
If you prefer to do it all in 1 line:
Object obj=((Question) (map.get('o'))).clone();

Related

Why the cast is necessary in this case?

class MyClass {
private String str;
public MyClass(String str){
this.str = str;
}
public int compare(Object o) {
return str.compareTo(((MyClass)o).str); //line No.8
}
}
class Client {
public static void main(String[] args) {
MyClass m = new MyClass("abc");
MyClass n = new MyClass("bcd");
System.out.println(m.compare(n));
}
}
Why in this snippet of code the cast (MyClass)o in line number 8 is necessary, despite the fact that the Client invokes a compare method with arguments which are instances of MyClass class?
When I modify the compare method in MyClass class to form like below:
public int compare(Object o) {
System.out.println(o.getClass());
System.out.println(((MyClass)o).getClass());
return str.compareTo(((MyClass)o).str);
}
Then, the Client will produce the following result:
class MyClass
class MyClass
Thus I don't understand why the cast above is required and why I can't just do like that (without cast to MyClass):
public int compare(Object o) {
return str.compareTo(o.str);
}
Because when I do that, I get the compile time error:
str cannot be resolved or is not a field
This comes down to what the compiler knows at compile time. At compile time it knows that what is going to be passed into this method is of type Object. That means that it can guarantee the methods that are associated with the class Object, but not the methods of type MyClass.
Because that compare method takes any argument of type Object, or a subclass, you could pass anything in. What if I make a class MyOtherClass like this..
public class MyOtherClass {
public String notStr;
}
And I do something like..
MyOtherClass myOtherClass = new MyOtherClass();
MyClass myClass = new MyClass();
myClass.compare(myOtherClass);
Without the cast, you've now got a situation where at runtime, it attempts to access a field that is not there. The cast is put in place to guarantee that the object is of the correct type, or it will fail before it attempts to access that field.
Just as an Aside
I've been working extensively with a language called Groovy. It is a language that essentially sits on top of Java, but it supports things like dynamic binding and loose typing (which is what you're after here). If this kind of functionality is a must have for you, then I would recommend checking out the documentation.
o's type in compare is an Object. This means the parameter it could be a MyClass instance, but it also could not. Object doesn't have any field called str (as that one belongs to MyClass), so there's no way to get that field from it, and so the code can't compile. If you cast to MyClass, however, it will have a field called str, and so it will be able to access it.

Dynamically creating and populating class inside method in java

Though my question seems repetition, but I am new to Reflections and could find solution to the exact problem.
I need to write a method, which any class can call to populate its data. For simplicity, I created a class say MappingHelper, with a Factory like method 'Create' which will create its own instance. I need to then populate this instance and return it.
public final Class MappingHelper{
public final Object getBENodeData(Class<?> classRef, String className){
Class myClass = Class.forName(classRef.getName());
Method method = classRef.getMethod("Create",(Class<?>[])null);
Object obj = method.invoke(null, (Object[]) null);
}
}
I need to typecast obj to same type as of 'classRef' so that I can call its instance methods.
Could someone help?
What you're trying to do is not possible with reflection and with your current setup. Even if you manage to cast the object to classRef, you wouldn't know what instance methods to call since getBENodeData presumably can take any type.
What you can do is call the method from a location where the type is known, and cast to it.
Object obj = getBENodeData(MyType1.class, MyType1.class.getName());
MyType1 myType1 = (MyType1) obj;
myType1.setId(..);
Object obj2 = getBENodeData(MyType2.class, MyType2.class.getName());
MyType2 myType2 = (MyType2) obj2;
myType2.setName(..);

How to convert string type to my own user class type in java

I have two classes like FirstClass and SecondClass. In the FirstClass I declared a variable with String type and then I assigned that variable to the SecondClass type. But it shows an exception. Please help.
Here is the code.
FirstClass.java
public static void main(String[] args) {
// TODO Auto-generated method stub
SecondClass sc;
String a = "world";
Object obj = a;
sc = (SecondClass) obj;
System.out.println("" + sc);
}
ErrorMessage.
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to com.study.SecondClass
at com.study.FirstClass.main(FirstClass.java:13)
Java is very strongly typed. There's no way to do this in Java. Java remembers the type - "world" is not a SecondClass object and can't be forced into it.
Even if you had two classes that were identical, say ClassOne and ClassTwo - you still couldn't convert between them using this approach.
One thing you could do though would be to add a constructor in SecondClass that took a String and would give you an object of type SecondClass based on that String. But even then, the String and the SecondClass object would be distinct.
Object obj = a;
sc = (SecondClass) obj;
At compile time you are telling java compiler that your object obj is in fact an object of class SecondClass. So it would compile fine. But at runtime it will know that obj is not an instance of SecondClass. So it would throw Exception at runtime. You just cannot cast anything to anything.
Usecase :
Type casting makes sense in case of polymorphism. For example you have used polymorphic reference to subclass object. At a later point of time you need to use some function that is defined and implemented only in the subclass. Then you need to type cast it to that subclass(which in fact your object is) and then you call the required function on it.

Understanding Object.clone() in Java

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));
}

Java run time class reflection

Say if I have a class named Car I can use the following line of code in certain situations.
Car.class
My question is there a way I can make the same type of call if a user supplies a class name at run time. Have tried something similar to the below but no joy, is there a way i can do it.
String className = "Car";
Class.forName(className ).class;
Also I need to be able to cast dynamically, if the user specifies a list of objects I need to be able to dynamically cast.
e.g. instead of Car myCar = (Car) object
I need to be able to have to the user specify the name/type of class at run time so that I need to be able to do something along the lines of ClassName myObj = (ClassName) object.
Class.forName("Car") already returns the same as Car.class.
For casting, you can then use Class.forName("Car").cast(object), which would return a Car object. Take a look at the API, mostly the java.lang.Class part of it.
Also, since you're casting # runtime, there's no type safety, and you should check whether object extends or implements Car before doing it, otherwise you'll get an exception. A question I asked ~ a year ago and the answers there may be relevant to you as well.
Though, as others already said, this smells & you could probably redesign it in a better way, also note that this type of casting will typically be pretty slow because Java needs to examine the type hierarchy (it needs to throw a ClassCastException if it can't cast to Car).
Given the nature of the question, most of the answers to this are straight from the Reflection API documentation. I would suggest you take a look at this: http://docs.oracle.com/javase/tutorial/reflect/class/index.html. If this does not help and you need help with something specific, we can look at that.
What you are looking for is a feature called Reflection in the Java programming language.
It allows an executing Java program to examine or "introspect" upon itself, and manipulate internal properties of the program. For example, it's possible for a Java class to obtain the names of all its members and display them.
A Simple Example from http://java.sun.com
import java.lang.reflect.*;
public class DumpMethods {
public static void main(String args[])
{
try {
Class c = Class.forName(args[0]);
Method m[] = c.getDeclaredMethods();
for (int i = 0; i < m.length; i++)
System.out.println(m[i].toString());
}
catch (Throwable e) {
System.err.println(e);
}
}
}
For an invocation of:
java DumpMethods java.util.Stack
the output is:
public java.lang.Object java.util.Stack.push(
java.lang.Object)
public synchronized
java.lang.Object java.util.Stack.pop()
public synchronized
java.lang.Object java.util.Stack.peek()
public boolean java.util.Stack.empty()
public synchronized
int java.util.Stack.search(java.lang.Object)
Here is an example of creating objects at runtime:
import java.lang.reflect.*;
public class constructor2 {
public constructor2()
{
}
public constructor2(int a, int b)
{
System.out.println(
"a = " + a + " b = " + b);
}
public static void main(String args[])
{
try {
Class cls = Class.forName("constructor2");
Class partypes[] = new Class[2];
partypes[0] = Integer.TYPE;
partypes[1] = Integer.TYPE;
Constructor ct
= cls.getConstructor(partypes);
Object arglist[] = new Object[2];
arglist[0] = new Integer(37);
arglist[1] = new Integer(47);
Object retobj = ct.newInstance(arglist);
}
catch (Throwable e) {
System.err.println(e);
}
}
}
You can read more about it here and here - for indepth view
Also look here:
What is reflection and why is it useful?
You want to interact with myObj, so rather than going through these gymnastics, think about adding an interface that models the interactions you want to have with the objects, then use that interface in the code. The classes supplied by the user can then be validated to implement the necessary interface and errors raised appropriately.
The expression Car.class returns the java.lang.Class object for class Car.
A statement Class.forName("Car") will also return the java.lang.Class object for class Car (assuming that class Car is in the default package). Note: No need to append .class; that would give you the Class object of class Class itself, which is not what you want.
Class Class has methods to check if an object is an instance of the class that the Class instance represents (hope this is not too confusing...). Since you don't know the name of class Car at compile time, you're not going to have any kind of compile time type safety.
Lookup the API documentation of java.lang.Class.

Categories

Resources