Java generic, use methods of original class
What I want to do is, create a function that returns a String with generic arguments. Then I need to use a method getName() that is for the specific class (better explain with the code).
Here is the code:
protected StringBuilder createJSON(Collection<E> jsonData) {
StringBuilder JSONBuilder = new StringBuilder();
JSONBuilder.append("{\"options\":[");
int count = jsonData.size();
for(Object obj: jsonData) {
count--;
JSONBuilder.appe开发者_开发百科nd("{\"label\":\"" + obj.getName() + "\",\"value\":\"" + obj.getName() + "\"}");
if(count>0) {
JSONBuilder.append(",");
}
}
JSONBuilder.append("]}");
return JSONBuilder;
}
createJSON takes a generic collection of objects, the problem is when I need to use getName(). the object that I pass to this function are com.opensymphony.user.UserManager and com.atlassian.jira.ComponentManager, both with getName() method.
the problem is when I need to use getName(). the object that I pass to this function are com.opensymphony.user.UserManager and com.atlassian.jira.ComponentManager, both with getName() method.
You want duck typing. Java doesn't have it. You're out of luck.
Since presumably those classes don't implement an interface with the method you need and you can't change them, your options are:
- Come up with some overengineeded design pattern
- Pragmatically forget about clean OO design and just use
instanceof
These two objects don't implement the same interface that declares getName()
method. You'll have to cast the object to one of these two classes and invoke the method or use reflection.
The only way to achieve this with generics is to add an interface which defines getName()
to all classes which can appear in the collection and then use Collection<E extends IFace>
(where IFace
is the name of your new interface).
From the names you specify, I'm pretty sure that you can't retrofit an interface to both.
Which leaves you with a wrapper class: You must wrap your elements in two helper classes which implements the interface and delegates the call to getName()
to the real class (see adapter or delegate pattern).
You can call method of object only if class/interface of reference to it declares the method. In your case you have to either:
- cast to ComponentManager or UserManager and then call getName()
- define your own
interface Nameable { public String getName(); }
Make both classes to implement this interface. Now argument of your method will beCollection<E extends Nameable> jsonData
, so you will be able to invoke this method without casting. - Use reflection :(
精彩评论