Dynamic Object Casting
Hello,
I need to sort an ArrayList. I use Collections.sort(ArrayList, Comparator) method.
This is how I define my Comparator class
class ComparatorCreatorimplements Comparator{
UserMaintenanceController u =new UserMaintenanceController();
int inter=0;
public ComparatorCreator(int val){
inter=val;
}
publicint compare(Object u1, Object u2){
//System.out.println("String> "+u1.getClass().toString());
System.out.println("Object> "+u1.getClass().getName());
//Object o=u1.getClass().getName();
//Error: Doesn't compile
//UserBean b1=(u1.getClass().getName())u1;
//Error end
UserBean b1=(UserBean)u1;
UserBean b2=(UserBean)u2;
int res=0;
switch (inter){
case 1: res=b1.getUserId().compareTo(b2.getUserId());
break;
case 2: res=b1.getUserName().compareTo(b2.getUserName());
break;
case 3: res=b1.getUserRole().compareTo(b2.getUserRole());
break;
default: res=b1.getUserName().compareTo(b2.getUserName());
}
return res;
}
}
As you can see I hard code every statement where I need to cast a class.
Now here is an issue.
I have several other ArrayLists in other classes that contain different beans
for e.g. CustomerBean, DealerBean, etc...(ArrayList of CustomerBean etc...)
I need to sort them as well. Sorting would require a Comparator. What I hope to achieve is to create a single piece of code that will create Comparator based on the class and public methods it has. So all I had to do is to call a method and pass it a field that Comparator needs to use.
Is there anyway to Dynamically cast Object into the appropriate class based ongetName()method?
Is there a way to execute method within the above class without knowing what the above class is?
[2877 byte] By [
svagera] at [2007-11-26 19:12:10]

If you really give it some thought you'll see that the concept doesn't actually make sense.
When you cast something you are telling the compiler what that it can assume it's a member of the class or interface, and access the fields and methods accordingly/.
If you don't know the target class at compile time, you wouldn't be telling the compiler anything useful.
And at runtime u1 is already of the class u1.getClass().
As I see it, you have a couple reasonable choices:
1) Have the beans implement an interface that exposes the properties you wish to sort, and let the Comparator sort implementations of that interface.
2) Use reflection to get the sortable properties. There are several APIs for beans that make this less painful (Jakarta's BeanUtils, Spring, etc.).
~
import java.lang.reflect.*;
import java.util.*;
class CoolComparator<T> implements Comparator<T> {
private Method method;
public CoolComparator(Class<T> cls, String methodName) throws NoSuchMethodException {
method = cls.getMethod(methodName);
}
public int compare(T o1, T o2) {
try {
Comparable result1 = (Comparable) method.invoke(o1);
Object result2 = method.invoke(o2);
return result1.compareTo(result2);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
}
}
public class CCTest {
String s;
Integer i;
public CCTest(String s, Integer i) {
this.s = s;
this.i = i;
}
public String getS() {return s;}
public Integer getI() {return i;}
public String toString() { return "(" + s + "," + i + ")";}
public static void main(String[]args) throws NoSuchMethodException {
CCTest[] data = {new CCTest("hello", 42), new CCTest("world", 17)};
List<CCTest> list = new ArrayList<CCTest>(Arrays.asList(data));
Collections.sort(list, new CoolComparator<CCTest>(CCTest.class, "getS"));
System.out.println(list);
Collections.sort(list, new CoolComparator<CCTest>(CCTest.class, "getI"));
System.out.println(list);
}
}
> As I see it, you have a couple reasonable choices:
>
> 1) Have the beans implement an interface that exposes
> the properties you wish to sort, and let the
> Comparator sort implementations of that interface.
>
> 2) Use reflection to get the sortable properties.
> There are several APIs for beans that make this less
> painful (Jakarta's BeanUtils, Spring, etc.).
>
> ~
Can you provide me with the code example that uses standard API? I can't use Spring or any other framework without it being approved first by architects.
Thanks
> class CoolComparator<T> implements Comparator<T>Ah, the "Old Number Two"?.. :o)~
> Can you provide me with the code example that uses> standard API?See reply #3. ~
Yeah, While I was typing my question someone posted a response to it :)The only question is. What is <> construct mean?ThanksMessage was edited by: svager
> The only question is. What is <> construct mean?
[url=http://java.sun.com/docs/books/tutorial/extra/generics/]Generics in the Java?Programming Language[/url]
[url=http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html]Java Generics FAQs[/url], by Angelika Langer
~
The pointy brackets are generic types: http://java.sun.com/docs/books/tutorial/extra/generics/index.html
If you are aren't up to speed on generics or are using an older version of
Java (<1.5) , you can just strip them out:
import java.lang.reflect.*;
import java.util.*;
class CoolComparator implements Comparator {
private Method method;
public CoolComparator(Class cls, String methodName) throws NoSuchMethodException {
method = cls.getMethod(methodName);
}
public int compare(Object o1, Object o2) {
try {
Comparable result1 = (Comparable) method.invoke(o1);
Object result2 = method.invoke(o2);
return result1.compareTo(result2);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
}
}
public class CCTest {
String s;
Integer i;
public CCTest(String s, Integer i) {
this.s = s;
this.i = i;
}
public String getS() {return s;}
public Integer getI() {return i;}
public String toString() { return "(" + s + "," + i + ")";}
public static void main(String[]args) throws NoSuchMethodException {
CCTest[] data = {new CCTest("hello", 42), new CCTest("world", 17)};
List list = new ArrayList(Arrays.asList(data));
Collections.sort(list, new CoolComparator(CCTest.class, "getS"));
System.out.println(list);
Collections.sort(list, new CoolComparator(CCTest.class, "getI"));
System.out.println(list);
}
}
> The pointy brackets are generic types:
> http://java.sun.com/docs/books/tutorial/extra/generics
> /index.html
>
> If you are aren't up to speed on generics or are
> using an older version of
> Java (<1.5) , you can just strip them out:
>
Yes, I am using 1.4.2
> The pointy brackets are generic types:
> http://java.sun.com/docs/books/tutorial/extra/generics/index.html
O pointy birds, o pointy pointy,
Anoint my head, anointy-nointy.
-- Pointy Birds, by John Lillison, England's Greatest One-Armed Poet
~
> import java.lang.reflect.*;
> import java.util.*;
>
>
> class CoolComparator<T> implements Comparator<T> {
>private Method method;
> public CoolComparator(Class<T> cls, String
> methodName) throws NoSuchMethodException {
>method = cls.getMethod(methodName);
>
>public int compare(T o1, T o2) {
>try {
> Comparable result1 = (Comparable)
> method.invoke(o1);
>Object result2 = method.invoke(o2);
> return result1.compareTo(result2);
>} catch (IllegalAccessException e) {
>throw new RuntimeException(e);
>} catch (InvocationTargetException e) {
> throw new RuntimeException(e);
>
>}
>
Um... I get compile time errors.
Information:Compilation completed with 3 errors and 0 warnings
Information:3 errors
Information:0 warnings
C:\cvssource\TraseTrak\Source\java\com\monsanto\ag\trasetrak\maintenance\CCTest.java
Error:Error:line (9)getMethod(java.lang.String,java.lang.Class[]) in java.lang.Class cannot be applied to (java.lang.String)
Error:Error:line (14)invoke(java.lang.Object,java.lang.Object[]) in java.lang.reflect.Method cannot be applied to (java.lang.Object)
Error:Error:line (15)invoke(java.lang.Object,java.lang.Object[]) in java.lang.reflect.Method cannot be applied to (java.lang.Object)
Thanks
DrLaszloJamf's code compiles fine (with a warning). See reply #9.~
My mistake. In 1.4 you aren't benefitting from varargs:
import java.lang.reflect.*;
import java.util.*;
class CoolComparator implements Comparator {
private static final Object[] EMPTY = new Object[0];
private Method method;
public CoolComparator(Class cls, String methodName) throws NoSuchMethodException {
method = cls.getMethod(methodName, new Class[0]);
}
public int compare(Object o1, Object o2) {
try {
Comparable result1 = (Comparable) method.invoke(o1, EMPTY);
Object result2 = method.invoke(o2, EMPTY);
return result1.compareTo(result2);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
}
}
public class CCTest {
String s;
Integer i;
public CCTest(String s, Integer i) {
this.s = s;
this.i = i;
}
public String getS() {return s;}
public Integer getI() {return i;}
public String toString() { return "(" + s + "," + i + ")";}
public static void main(String[]args) throws NoSuchMethodException {
CCTest[] data = {new CCTest("hello", 42), new CCTest("world", 17)};
List list = new ArrayList(Arrays.asList(data));
Collections.sort(list, new CoolComparator(CCTest.class, "getS"));
System.out.println(list);
Collections.sort(list, new CoolComparator(CCTest.class, "getI"));
System.out.println(list);
}
}
Sorry, posted the wrong quote.
Here is the code
import java.lang.reflect.*;
import java.util.*;
class CoolComparator implements Comparator {
private Method method;
public CoolComparator(Class cls, String methodName) throws NoSuchMethodException {
method = cls.getMethod(methodName);
}
public int compare(Object o1, Object o2) {
try {
Comparable result1 = (Comparable) method.invoke(o1);
Object result2 = method.invoke(o2);
return result1.compareTo(result2);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
}
}
public class CCTest {
String s;
Integer i;
public CCTest(String s, Integer i) {
this.s = s;
this.i = i;
}
public String getS() {return s;}
public Integer getI() {return i;}
public String toString() { return "(" + s + "," + i + ")";}
public static void main(String[]args) throws NoSuchMethodException {
CCTest[] data = {new CCTest("hello", new Integer(42)),
new CCTest("world", new Integer(17))};
List list = new ArrayList(Arrays.asList(data));
Collections.sort(list, new CoolComparator(CCTest.class, "getS"));
System.out.println(list);
Collections.sort(list, new CoolComparator(CCTest.class, "getI"));
System.out.println(list);
}
}
This is what I have got and it bombs with this errors
Information:Compilation completed with 3 errors and 0 warnings
Information:3 errors
Information:0 warnings
C:\\maintenance\CCTest.java
Error:Error:line (9)getMethod(java.lang.String,java.lang.Class[]) in java.lang.Class cannot be applied to (java.lang.String)
Error:Error:line (14)invoke(java.lang.Object,java.lang.Object[]) in java.lang.reflect.Method cannot be applied to (java.lang.Object)
Error:Error:line (15)invoke(java.lang.Object,java.lang.Object[]) in java.lang.reflect.Method cannot be applied to (java.lang.Object)
What version of Java do you have?
> My mistake. In 1.4 you aren't benefitting from> varargs:Few, and I thought that I am going nuts and no longer able to compile a source code :)
> What version of Java do you have?
JavaSE 6. In 5, varargs were introduced. Class' getMethod signature is:
Method getMethod(String name, Class<?>... parameterTypes)
... meaning you can call it like this:
m = cls.getMethod("name"); //or
m = cls.getMethod("name", String.class); //or
m = cls.getMethod("name", String.class, XYZ.class); //or
m = cls.getMethod("name", new Class[]{String.class, XYZ.class}); //ugh
Previous to 1.5 that method's signature was just:
Method getMethod(String name, Class[] parameterTypes)
Hence my adjustments in code.
> My mistake.Mine, too. I didn't check the 1.4 version.~
Miracle !!!!It WORKS !!!! YAHOOOOO!!!!Thanks a bunch.