The Object.clone() method in Java is pretty special, as instead of returning a copy of the object that is to be cloned with the Object type, it returns the correct Object type. This can be better described with the following code:
class A implements Cloneable
{
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class B extends A {
}
public class MainABC {
public static void main(String[] args) throws CloneNotSupportedException {
B b = new B();
B b1 = (B)b.clone(); //see here that we are using A's .clone(). The only
//thing it does is call Object's clone().
System.out.println(b1.getClass()); //but as we see here, its not an Object
//its a B!
}
}
So, could anyone explain if possible if is there anyway to replicate what happens inside Object.clone()'s method?
It is definitely true that Object.clone() does a few things that simply can not be achieved in Java.
From Josh Bloch on Design: Copy Constructor versus Cloning (emphasis mine):
Object's clone method is very tricky. It's based on field copies, and it's "extra-linguistic." It creates an object without calling a constructor. There are no guarantees that it preserves the invariants established by the constructors.
Object.clone() does something that isn't supposed to be allowed by the language. That is why, among many other reasons, clone() is broken.
(If you haven't already, you should also read his book Effective Java, to understand why he (and many others) think that Java's clone() and Cloneable is broken).
If you just want to create an object of the same class as another arbitrary object, then this is actually quite achievable, with some caveat (namely that not all types are publicly instantiable) by using reflection.
Here's an example of how to use reflection to:
Find out the class of an object at run-time
List its declared fields, methods, and constructors
Find its copy constructor (if any), and tries to invoke it using the given object as
parameter.
import java.lang.reflect.*;
public class NewInstance {
static void print(String label, Object[] arr) {
System.out.println(label);
for (Object o : arr) {
System.out.println(o);
}
System.out.println("---");
}
static Object newInstance(Object o) {
Class<?> c = o.getClass();
System.out.println("Class is " + c);
print("FIELDS:", c.getDeclaredFields());
print("METHODS:", c.getDeclaredMethods());
print("CONSTRUCTORS:", c.getDeclaredConstructors());
try {
Constructor<?> cc = c.getDeclaredConstructor(c);
o = cc.newInstance(o);
} catch (NoSuchMethodException e) {
System.out.println("No copy constructor found!");
} catch (IllegalAccessException e) {
System.out.println("Copy constructor inaccessible!");
} catch (InstantiationException e) {
System.out.println("Instantiation failed!");
} catch (InvocationTargetException e) {
System.out.println("Copy constructor threw " + e.getCause());
}
return o;
}
public static void main(String args[]) {
Object o1 = "hello";
Object o2 = newInstance(o1);
boolean success = (o1 != o2) && (o1.equals(o2));
System.out.println("Attempt " + (success ? "succeeded!" : "failed :("));
}
}
Output:
Class is class java.lang.String
FIELDS:
// (omitted)
METHODS:
// (omitted)
CONSTRUCTORS:
public java.lang.String()
public java.lang.String(java.lang.String) // this is what we're looking for!
// (rest omitted)
---
Attempt succeeded!
Note that this is just an example to show type can be inspected at run time and a copy constructor can be looked for and invoked. As is, it doesn't work if o is an ArrayList, because it has no constructor that takes an ArrayList (it does have one that takes a Collection, which an ArrayList is).
I'll leave it to you as an exercise on how to expand the search for the copy constructor to include these compatible overloads.
I've never heard or seen a language construct that provides you the functionality that clone give you for free.
You can imitate it, but I don't believe you can replicate the behavior.
The Objenesis library can be used to create instances of arbitrary classes even if they do not have a no-args constructor. It uses various tricks for each JVM to accomplish this. You can use that together with a bit of reflection code to copy all field values from the source object to the destination.
I think you have not even tested the code you typed here!
If you try to compile this code you get errors. First of all the return super.clone() gives you an error of "Type mismatch: cannot convert from Object to A"
Second (i will assume this was a mistype) you did not create an instance of B. You said
B = new B();
Even if we change that to
B b = new B();
B b1 = b.clone();
You will get an error because b.clone() will return an instance of class A.
So sorry but you describe does not happen... You need a cast to get what you want.
So to sum up:
public class A extends Object {
public A clone() {
return super.clone(); // Error "Type mismatch: cannot convert from Object to A"
}
public static void main(String[] args) {
B b = new B();
B b1 = b.clone(); // Error "Type mismatch: cannot convert from A to B"
}
}
class B extends A {
}
EDIT: I'm afraid you got it wrong again. What you did returns an instance of B because you cast it to a B instance. It would return B even if you cast something completely different... For instance
B b = (B)(new JLabel());
System.out.println(b.class);
This will print the class of B. Actually it WOULD print the class of B if it ever got there... You will get an exception before it gets there... To have what you want you have to manually override the clone method and provide your own implementation. You question is not valid at all.. You should delete it but you can't since you have upvoted answers... I would vote to close at least...
How about this?
public class A {
public static void main(String[] args) {
B b = new B();
B b1 = (B)b.getNew();
System.out.println(b1.getClass());
}
public Object getNew() {
try {
return getClass().newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
}
class B extends A {
}
Related
Downcasting is when child class refers to the object of Parent class. I tried doing it without the instanceof operator.
class Food { }
class bread4 extends Food {
static void method(Food a) {
bread4 b=(bread4)a;
System.out.println("ok downcasting performed");
}
public static void main (String [] args) {
Food a=new bread4();
bread4.method(a);
}
}
Can anyone help me in this by using instanceof operator?
instanceof operator provides runtime type checking. For instance, if you had a class Food and two subtypes, Bread4 and Bread5, then:
static void method(Food a) {
Bread4 b = (Bread4) a;
System.out.println("Downcasting performed");
}
calling this method like:
Food four = new Bread4();
Food five = new Bread5();
Bread4.method(four); //the cast inside is done to Bread4, therefore this would work
Bread4.method(five); //the object of type Bread5 will be cast to Bread4 -> ClassCastException
To avoid this, you use the instanceof operator
static void method(Food a) {
if (a instanceof Bread4) {
Bread4 b = (Bread4) a;
System.out.println("Downcasting performed");
}
}
therefore, in case you call
Bread4.method(five)
the check return false so no ClassCastException occurs.
Hope this answers your question.
Here is how you can use the instanceof operator:
static void method(Food a) {
if (a instanceof bread4) {
bread4 b = (bread4) a;
System.out.println("Downcasting performed");
}
}
The instanceof operator takes an object on the left hand side and checks if it is an instance of the right hand side argument which is a class.
obj instanceof Claz
This returns true if the class of obj is an instance of Claz.
On a side note, I also do highly recommend that you follow Java naming conventions. Instead of naming your class bread4, name it Bread4.
Classes should start with upper case letters whereas variables and methods should start with lower case letters.
I have a class with multiple methods which accepts different params and return different type like class foo in below example:-
class foo{
public void A(int a , int b){
// do somthing.
}
public String B(int a , String b){
// do somthing.
return "a";
}
public Object C(String a , String b){
// do somthing.
return null;
}
public int D(Long a , String b , String c){
// do somthing.
return 1;
}
}
public class bar {
public static void main(String[] args) {
try {
Class c = Class.forName("foo");
Object t = c.newInstance();
Method[] methods = c.getDeclaredMethods();
for(Method m : methods){
String methodName = m.getName();
if(methodName.equalsIgnoreCase("A")) {
// How to call method with its argument and return the result using reflection.
m.invoke(t,);
break;
}
}
}catch (InstantiationException e){
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
// Handle any exceptions thrown by method to be invoked.
e.printStackTrace();
}
}
}
Now i want to create a utility method which accepts the method name and arguments and call the corresponding method using the reflection. Let me know how can i pass different method params using the generic utility method and return the result(it may return int,string,object as illustrated in the example) from the reflection code.
In your sample code, the public Object invoke(Object obj, Object... args) method of the Method class takes as second argument a varargs. So you can invoke the A(int, int) method in this way :
m.invoke(t, 3, 4);
But this will not solve really your problem.
Let me know how can i pass different method params using the generic utility method and return the result(it may return int,string,object as illustrated in the example) from the reflection code.
It is a really poor design as you want to use reflection to do very specific things : call specific methods with specific arguments with a single entry point method.
It's error prone and slower.
For example you could have a method with 2 parameters in the entry point method :
A string for method name
varargs of Object for parameter values.
How use it ?
Without type checking and by counting the position of each parameter passed in the declared method : very error prone.
Besides, if you add/remove or change a parameter in the used class, your reflective code will compile fine while at runtime it will raise a exception.
It seems really not a suitable case for reflection.
I have a super class A, and classes B, C and D that extend A.
class A {}
class B extends A {}
class C extends A {}
class D extends A {}
Then I have a list like this:
[B.class, C.class, D.class]
I take a random item from the list and instantiate it like so:
Object obj = list.get(i).newInstance()
Now I need to pass obj to a method that accepts objects of type A as a parameter.
A a = (A) obj
causes java to throw an exception (Either InstantiationException or IllegalAccessException, I don't know because android studio won't stop at breakpoints inside the catch, and any attempt to save information about the exception from the catch results in null...).
I understand why I can't dynamically specify the new object type and then cast obj to that type, but if they all share the common parent, I don't see why it wouldn't work.
Can anybody enlighten me how to fix what I'm currently doing, or achieve the same thing in a similar way?
Thanks! /Max
The newInstance method can throw an InstantiationException or IllegalAccessException, hence the warning you're probably seeing in your IDE if this call isn't wrapped in a try/catch. Your simple example seems to work fine though.
class A {}
class B extends A {}
class C extends A {}
public class Test {
public static void main(String[] args) throws Exception {
List<Class> list = new LinkedList<Class>();
list.add(B.class);
list.add(C.class);
Object obj = list.get(0).newInstance();
A a = (A) obj;
System.out.println(a instanceof B);
}
}
Prints "true"
In the end this was due to a bug with android studio. Rewriting the code fixed the problem and I wasn't able to reproduce this issue
Other symptoms that future searchers might find useful:
android studio would not stop at breakpoints inside a catch block
Any attempt to save information about the exception inside the catch resulted in null (see example below)
:
Exception ex = null;
try {
// do something that raises an exception
ex = new Exception();
} catch (Exception ex) {
ex = ex;
}
// ex == null
As pointed out by the other answers, what I was describing in my question does not normally raise an exception.
The code seems to be working absolutely fine. I am not understanding your question.
package testplayground;
import java.util.ArrayList;
import java.util.List;
class A {
void print() {
System.out.println("inside A");
}
}
class B extends A {
public void print() {
System.out.println("inside B");
}
}
class C extends A {
public void print() {
System.out.println("inside C");
}
}
class D extends A {
public void print() {
System.out.println("inside D");
}
}
public class TestPlayGround {
public static void main(String[] args) {
try {
List<Class> list = new ArrayList<Class>();
list.add(B.class);
list.add(C.class);
list.add(D.class);
for (Class classObj : list) {
Object obj = classObj.newInstance();
A a = (A) obj;
methodA(a);
}
} catch (Exception e) {
e.printStackTrace();
}
}
private static void methodA(A a) {
a.print();
}
}
output:-
inside B
inside C
inside D
Lets say we have a baseclass called A and some subclasses (B,C,D, etc.). Most subclasses have the method do() but the baseclass does not.
Class AA provides a method called getObject(), which will create an object of type B, or C or D, etc., but returns the object as type A.
How do I cast the returned object to the concrete type and call its do() method, if this method is available?
EDIT:
I'm not allowed to change the implementation of Class A, the subclasses or AA, since im using a closed Source API.. And yeah, it does have some design issues, as you can see.
You can test with instanceof and call the do() methods:
A a = aa.getObject();
if (a instanceof B) {
B b = (B) a;
b.do();
}
// ...
I think a better idea is to actually have class A define the do() method either as an abstract method or as a concrete empty method. This way you won't have to do any cast.
If you are not allowed to change any of the classes than you could define a class MyA extends A which defines the do() method and MyB, MyC,... and a MyAA that would basically do what AA does, just that it returns objects of type MyB, MyC....
If this is not ok then I don't see another way than checking if the returned object is of type B and do a cast to B and so on.
Assuming A defines do, and it is not private, you can just call it without a cast, no matter the subclass that AA returns. That's one of the features of polymorphism. At runtime, the interpreter will use the correct (i.e. the implementation of the actual class) version of do.
First of all it would be a better approach to make Class A as an abstract Class with do() as an Abstract method in it......
Moreover if you still want the way you want to do it..then
Do an explicit cast.
B b = (B) a; // a is a casted back to its concrete type.
Moreover you should keep in mind this very important behaviour of the Compiler.
The Object Reference Variable of Super Type must have the method to be called, whether the Sub Type Object has or not.
Eg:
A a = new B();
- To call a method, do() on Object Reference Variable of Type A, class A must have the go() method.
If you are not allowed change A but you can change the subclasses then you can make an interface with the method do() and let all the subclass implement that interface.
public interface Doer {
public void do();
}
public class B extends A implements Doer {
//implement do method
}
//.. same for other subclass
Then you don't need a cast. Otherwise you will need some explicit downcasts.
What you are describing seems to me like you want to invoke Derived Class methods on Base class reference..
But for that, you need to have your methods in your base class also..
So, you need to declare your method do() in your base class A also.. If you don't want to give an implementation, let it be abstract, or let it be an empty method.. It will not matter..
Now, if you do the same thing you're explaining.. You won't need to do a typecast..
Because, appropriate Derived Class method will be invoked based upon - which derived class object does your base class reference point to
public abstract class A {
public abstract void do();
}
public class B extends A {
public void do() {
System.out.println("In B");
}
}
public class Test {
public static void main(String[] args) {
A obj = returnA();
obj.do(); // Will invoke class B's do() method
}
/** Method returning BaseClass A's reference pointing to subclass instance **/
public static A returnA() {
A obj = new B();
return obj;
}
}
Ok, just now saw your edit, that you are not allowed to change your classes..
In that case, you will actually need to do a typecast based on the instance of returned reference..
So, in main method above, after A obj = returnA(); this line add the following line: -
if (obj instanceof B) {
B obj1 = (B) obj;
}
But, in this case, you would need to check instanceof on each of your subclasses.. That can be a major problem..
Best way to do it have A class that method. But since you are not allowed to change any class. I would advice you to create a wrapper instance around all classes using reflections.
Static method in Below class is used just to show how to do it. You can have separate instance variable which can Wrap A in E.
public class E {
public static void doMethod(A a) {
Class<?> class1 = a.getClass();
Method method;
try {
method = class1.getDeclaredMethod("doMethod", null);// B, C, D has doMethod
method.invoke(a, null);
// I know to many exceptions
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
Second option is instance of for which you will have to check for the type and then cast it.
You can do this with a little work if the method invocations return instances of the class in question, which is your specific question (above).
import static java.lang.System.out;
public class AATester {
public static void main(String[] args){
for(int x: new int[]{ 0, 1, 2 } ){
A w = getA(x);
Chain.a(w.setA("a")).a(
(w instanceof C ? ((C) w).setC("c") : null );
out.println(w);
}
}
public static getA(int a){//This is whatever AA does.
A retval;//I don't like multiple returns.
switch(a){
case 0: retval = new A(); break;
case 1: retval = new B(); break;
default: retval = new C(); break;
}
return retval;
}
}
Test class A
public class A {
private String a;
protected String getA() { return a; }
protected A setA(String a) { this.a=a; return this; }//Fluent method
#Override
public String toString() {
return "A[getA()=" + getA() + "]";
}
}
Test class B
public class B {
private String b;
protected String getB() { return b; }
protected B setB(String b) { this.b=b; return this; }//Fluent method
#Override
public String toString() {
return "B[getA()=" + getA() + ", getB()=" + getB() + "]\n "
+ super.toString();
}
}
Test Class C
public class C {
private String c;
protected String getC() { return c; }
protected C setC(String c) { this.c=c; return this; }//Fluent method
#Override
public String toString() {
return "C [getA()=" + getA() + ", getB()=" + getB() + ", getC()="
+ getC() + "]\n " + super.toString();
}
}
The Chain class
/**
* Allows chaining with any class, even one you didn't write and don't have
* access to the source code for, so long as that class is fluent.
* #author Gregory G. Bishop ggb667#gmail.com (C) 11/5/2013 all rights reserved.
*/
public final class Chain {
public static <K> _<K> a(K value) {//Note that this is static
return new _<K>(value);//So the IDE names aren't nasty
}
}
Chain's helper class.
/**
* An instance method cannot override the static method from Chain,
* which is why this class exists (i.e. to suppress IDE warnings,
* and provide fluent usage).
*
* #author Gregory G. Bishop ggb667#gmail.com (C) 11/5/2013 all rights reserved.
*/
final class _<T> {
public T a;//So we can reference the last value if desired.
protected _(T t) { this.a = T; }//Required by Chain above
public <K> _<K> a(K value) {
return new _<K>(value);
}
}
Output:
A [get(A)=a]
B [get(A)=a, getB()=null]
A [getA()=a]
C [getA()=a, getB()=null, getC()=c)]
B [get(A)=a, getB()=null]
A [get(A)=a]
public class ExampleClass {
public static void main(String[] args) {
// TODO Auto-generated method stub
Horse hr1 = new Horse();
Horse hr2 = new Horse();
Horse hr3 = new Horse();
Horse hr4 = new Horse();
Set hrSet = new HashSet();
hrSet.add(hr1);
hrSet.add(hr2);
hrSet.add(hr3);
hrSet.add(hr4);
Horse hr;
String hor = "sher_pkg.Horse";
callHorse(hrSet,hor);
}
public static void callHorse(Set xSet,String clsName){
try {
Class hrt = Class.forName(clsName);
Iterator hritr = xSet.iterator();
while(hritr.hasNext()){
exam(hrt.cast(hritr.next()));
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static void exam(Object obj){ //I want to use exam(Horse hrr)
System.out.println(obj);
}
}
Here the argument for the exam function is an Object. But I want to have the argument be Horse... so what changes must be done in "exam(hrt.cast(hritr.next()))" method call? I don't want to explicitly use the class name Horse in callHorse()... So what am I supposed to do?
Thanks
Note: Code with sequences of "if (x instanceof MyClass) usually indicates that you are not using polymorphism enough. Code can usually be refactored to get rid of the need to test this. But I'll ignore this for the sake of answering the question asked.
You can do what you are trying to do, but not without some code changes. Method overloading cannot do what you need because in Java, method overloading is decided at compile time. Thus, if you have two methods in a class where both methods have the same name, same return type, but different parameter types, then any code invoking this overloaded method must make explicit which one will be invoked. Your current code does this with the types it provides due to the use of explicit casts but the fully dynamic version does not. If method overloading were decided at runtime, then your code would do what you want. But because it is decided at compile time, your code does not compile.
To solve your problem, you can use generics, or you can restructure your code. First I'll introduce a test harness that shows a very simplified version of what you're starting with:
public class Test {
public void test(Object obj) {
if (obj instanceof Horse) {
Horse c = (Horse) obj;
noise(c);
}
if (obj instanceof Cow) {
Cow c = (Cow) obj;
noise(c);
}
}
public void noise(Horse h) {
System.out.println("Neigh");
}
public void noise(Cow c) {
System.out.println("Moo");
}
public static void main(String[] args) {
Object o1 = new Horse();
Object o2 = new Cow();
Test tester = new Test();
tester.test(o1);
tester.test(o2);
}
}
class Horse {}
class Cow {}
This code runs and does what you would expect. It prints "Neigh" followed by "Moo".
You are trying to replace
if (obj instanceof Horse) {
Horse c = (Horse) obj;
noise(c);
}
with
if (obj instanceof Horse) {
handleNoise(obj, Horse.class);
}
and then adding the method to handle it (simplified):
void handleNoise(Object obj, Class clazz) {
noise(clazz.cast(obj));
}
and as I said before, this doesn't work the overloading of noise is decided at compile time. The compiler sees that you are casting, but does not know at compile time what the type is. So it cannot pick an overloading and compilation fails.
The best way to solve this is by using polymorphism, because polymorphism is decided at runtime. That is, have all of those classes implement some interface and then move the code in question into the individual classes. Here is an example that does this:
public class Test {
public void test(Animal obj) {
obj.noise();
}
public static void main(String[] args) {
Animal o1 = new Horse();
Animal o2 = new Cow();
Test tester = new Test();
tester.test(o1);
tester.test(o2);
}
}
interface Animal {
void noise();
}
class Horse implements Animal {
public void noise() {
System.out.println("Neigh");
}
}
class Cow implements Animal {
public void noise() {
System.out.println("Moo");
}
}
Notice how much simpler the test method is! If you can have each item implement an interface that handles what you call stringProp below, then you can simplify part way:
if (obj instanceof Cust) {
loopOverSet(c.getCustPhonSet());
} else if (obj instanceof Name) {
loopOverSet(c.getCustNameSet());
}
// and so on for the rest...
and then add the method:
void loopOVerSet(Set cxSet) {
if (cxSet != null && cxSet.size() > 0) {
Iterator cxSetIterator = cxSet.iterator();
while (cxSetIterator.hasNext())
{
((StringProp)cxSetIterator.next()).stringProp();
}
}
}
This assumes that the previously-overloaded methods stringProp have been moved into the individual classes CustPhone and CustName and so on and that these classes all implement some interface which I've called StringProp where this interface defines the method stringProp(). Since this code is using overriding instead of overloading it will be decided at runtime.
You might want to take a look at generics.
public static void callHorse(Set<Horse> xSet) {
Iterator<Horse> hritr = xSet.iterator();
while (hritr.hasNext()) {
exam(hritr.next());
}
}
public static void exam(Horse obj) { //I want to use exam(Horse hrr)
System.out.println(obj);
}
Of course in your example you could always just cast the objects. Why you don’t want to do that is beyond me.
When you say:
exam(Horse hrr)
you're telling the compiler that you want it to check all calls to exam() and make sure that each call provides a Horse object as an argument. However, in callHorse(), you're invoking exam() with a dynamically cast argument, and the compiler has no way to check the argument.
It's possible that you could work around this by using reflection and dynamically invoking the exam() method.
You could explicitly cast in the function call -
try {
Class hrt = Class.forName(clsName);
Iterator hritr = xSet.iterator();
while(hritr.hasNext()){
exam((Horse)hrt.cast(hritr.next()));
}
}
but I'm not really sure what you're trying to achieve here - If you're writing code that explicitly references Horses, why do you need to dynamically determine the class type from a string?
First things first,your set should be using either generics or explicitly defined as only holding Horse Objects.
(final Set xSet<Horse>, final String clsName){
...}
Fix that and you have fixed 90% of the issues.
It looks like your design is wrong for Java, and you can't directly do what you are asking for.
Perhaps you need to reshape your code to use the visitor pattern? Failing that, you need to explain your requirement instead of the solution that you want to use. In that way, we can tell you the proper Java solutions to your requirement.
I'm not sure it's possible or desirable to avoid having a reference to "Horse" in the callHorse method. Judging from the printstacktrace after a ClassNotFoundException, you throw a hard error if the class is not found for some reason.
Couldn't you, for the same reason, just cast to "Horse" and then catch the classcastexception if something in the Set is not a Horse?
Can you explain why it exactly is that you need to pass in the classname instead of the class?
Maybe you can also use method overloading, but I'd have to test this, because I'm not entirely sure what the precedence is in this case.
If you are doing a dynamic cast by using Class.cast() with an argument that you're passing to another function, then at compile time nothing is known about the type that you are passing. This is why you cannot use Horse as the argument type where you define the method, but then call the method using reflection in the way that you are. Your cast does very little except verify that -- as long as you don't get an Exception -- the set you pass in is entirely comprised of members of the Class you pass in the name of.
Note that the Class.cast() method was introduced in Java 5, meaning you have access to Generics if you have access to Class.cast(). Generics can help clean things up although they won't solve the problem you are trying to solve.
Using a Java 5 for loop you can rewrite your loop as follows:
public static void callHorse(Set<?> xSet, String clsName) {
try {
Class<?> hrt = Class.forName(clsName);
for (Object x : xSet) {
exam(hrt.cast(x));
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
This version is less cluttered and makes your cast more obvious. You are casting to an entirely arbitrary type. The cast may be to any type as long as the class definition can be loaded from the classpath. Thus, if your exam() method takes an argument of Horse then the compiler knows that it cannot guarantee that the call will succeed and the code fails to compile.
Even if you try overloading, it won't work. That is, if you create the methods:
public static void exam(Object obj) {
System.out.println("Object " + obj);
}
public static void exam(Horse obj) {
System.out.println("Horse " + obj);
}
the exam(Object) method will always be the one invoked. Try it.
The bottom line is that what you're trying to do cannot be done. You need to give us more information about exactly what your goal is before we can help you.
Why not write it like this? What exactly are your requirements?
public static void main(String[] args) {
Set<Horse> horses = new HashSet<Horse>();
horses.add(new Horse());
horses.add(new Horse());
horses.add(new Horse());
horses.add(new Horse());
callHorse(horses);
}
public static void callHorse(Set<Horse> horses) {
for (Horse horse : horses) {
exam(horse);
}
}
public static void exam(Horse horse) {
System.out.println(horse);
}
Depending on what you do in the exam() method, it might also make sense to make it an instance method of Horse, like this:
public static void main(String[] args) {
Set<Horse> horses = new HashSet<Horse>();
horses.add(new Horse());
horses.add(new Horse());
horses.add(new Horse());
horses.add(new Horse());
examineHorses(horses);
}
public static void examineHorses(Set<Horse> horses) {
for (Horse horse : horses) {
horse.examine();
}
}
// in Horse.java
public class Horse {
public void examine() {
System.out.println(this);
}
...
}
Is your real goal to have multiple versions of the exam() method, that take different types as parameters, and dynamically select the version needed at runtime?
You can do this explicitly with reflection. Here's an example program.
import java.lang.reflect.*;
public class Test {
public static void exam( Object o ) {
System.out.println( "Object version called" );
}
public static void exam( Test t ) {
System.out.println( "Test version called" );
}
public static void main (String[] args) {
try {
// Create an instance of Test but reference it as an Object
Object untypedTest = new Test();
// Calling exam directly will invoke the Object version
exam( untypedTest );
// But if we use reflection to select the version of exam
// that takes the desired class name, we can invoke it without
// even explicitly casting
String className = "Test";
Class[] examMethodParams = { Class.forName( className ) };
Method examMethod = Test.class.getMethod( "exam", examMethodParams );
Object[] actualParams = { untypedTest };
examMethod.invoke( null, actualParams );
} catch (Exception e) {
e.printStackTrace();
}
}
}
HI,
After searching through i found that dynamic typecast at runtime can't be performed. So what i was trying to figure out seems to be absurd.
I was trying to reduce the cyclomatic complexity of a method1. I was trying to create a method2 which contains the generalized pattern of the repetition pattern found in method1 and calling the method2 from method1 wherever necessary...
the pattern was like this in the first method..
if (obj instanceof Cust)
{
Cust c = (Cust) obj;
Set cxSet = c.getCustPhonSet();
CustPhon cx;
if (cxSet != null && cxSet.size() > 0)
{
Iterator cxSetIterator = cxSet.iterator();
while (cxSetIterator.hasNext())
{
cx = (CustPhon) cxSetIterator.next();
this.stringProp(cx);
}
}
//....pattern continues here... CustPhon is replaced by various classes like CustNam etc... Also getCustPhonSet by getCustNamSet etc...
}
so i thought of writing a generalized method for the above pattern like this::
public void dynamicIteration(Set xlSet, String clsName)
{
if (xSet != null && xSet.size() > 0)
{
try{
Class clsinstance = Class.forName(clsName);
Iterator itr = generalSet.iterator();
while(itr.hasNext())
{
this.stringProp(clsinstance.cast(itr.next()));// See this is wrong.. thats y i posted here by using a simple Horse example
}
}catch(ClassNotFoundException e)
{
e.printStackTrace();
}
}
}
Calling method2 from method 1
//process customer email address
Set cxSet = c.getCustPhonSet();
className = "pkg.CustPhon";
dynamicIteration(cxSet,className);
// Similarly for other patterns
By this way i must be able to reduce the cyclomatic complexity
This is what i was trying to do..
Hey i think this would solve the problem. You need to decide upon which object it is, so that u can call the corresponding operation, right???
Since we use the overriding comcepts the very functionality that s required can be achieved.
What is given by Eddie may be the most appropriate solution for this i guess?
YOu override the method in the respective classes so that on calling it goes the corressponding method.
U got it?