[jdom-interest] JDom and Java5
Mattias Jiderhamn
mj-lists at expertsystems.se
Sat Feb 23 12:39:18 PST 2008
(To be completely honest I have not read the whole post Rolf...)
Without having analyzed if this depends on some compiler parameter or
other project setting, here is what I experienced.
With return type List (as JDOM is today) I could do
List<Element> elements = XPath.selectNodes(doc, path)
and only get compiler warnings
With return type List<?> (Rolfs second version; which I believe are
equivalent to List<? extends Object>) I could do
List<Element> elements = (List<Element>) XPath.selectNodes(doc, path)
With return type List<Object> I cannot cast but have to do
List<Element> elements = new ArrayList<Element>();
for(Object o : XPath.selectNodes(doc, path))
elements.add((Element)o);
I think the last option is by far the least appealing (unless, as I
said, there is some setting to fix this).
In the choice between List and List<?>/List<? extends Object> the plain
List has the advantage of making the Java5 port more of a JAR
replacement. It does not require modifying the code to add the cast.
Also, Gregor points out that List is for "pre-generics legacy code" and
certainly, in this case it could be used to indicate that behinds the
scenes there is pre-generics legacy code, which in this case is Jaxen.
Therefore I personally vote for "List".
BUT there is actually a fourth alternative; add the expected output type
as a parameter to the method.
List<Element> elements = XPath.selectNodes(doc, path, Element.class);
List<Attribute> elements = XPath.selectNodes(doc, path, Attribute.class);
List<Object> elements = XPath.selectNodes(doc, path, Object.class); //
Mix of different types
This may be the most beautiful solution, but also the most noticeable
change with a new parameter. What about an overload with one legacy
version with List and one with the third parameter???
/Mattias
Rolf wrote (2008-02-23 15:51):
> Hi Gregor
>
> Hmm... actually, I somewhat disagree (in this particular
> circumstance). I have been thinking about this a bit more
>
> Here's the 'current' code behind the method (after I modified it
> yesterday)...
>
> public List<?> selectNodes(Object context) throws JDOMException {
> try {
> currentContext = context;
> return xPath.selectNodes(context);
> } catch (JaxenException ex1) {
> throw new JDOMException("XPath error while evaluating \"" +
> xPath.toString() + "\": " + ex1.getMessage(), ex1);
> } finally {
> currentContext = null;
> }
> }
>
> Here's the signature on the xPath method that is supplied by Jaxen:
>
> List <http://java.sun.com/j2se/1.4.2/docs/api/java/util/List.html>
> *selectNodes*(Object
> <http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Object.html>
> context) throws JaxenException
> <http://jaxen.codehaus.org/apidocs/org/jaxen/JaxenException.html>
>
> Given that XPath can return all sorts of values (not all of them are
> JDom Content (like Attribute which is not Content)), then we have a
> real problem with this method.
>
> There is no way I can see (even by modifying Jaxen) to return a list
> of any specific type other than Object. It would be real nice if an
> xpath that returned just Elements would have a return type of
> List<Element>, but that just isn't feasible.
>
> The next best thing is to return something appropriate, and that
> should be the same as what Jaxen would return if it were Generified.
>
> Thus, the best thing would be to consider things from Jaxen's POV, and
> let the 'client' sort it out.
>
> Since Jaxen does not know anything about the actual content in the
> 'context' (it is all delegated to a JDom specific implementation), and
> that implementation has to be able to return both Attribute and
> Content, the best that Jaxen could do is return List<Object>.
>
> The Jaxen code would have no option but to look something like:
>
> List<Object> ret = new XXXList<Object>();
> for (..... nodes in context ...) {
> if (... node matches the xpath ...) {
> ret.add(node);
> }
> }
>
>
> because it will potentially have to add Attributes, Elements, Text,
> etc. (and that's just for JDom, for other API's it will need other
> constructs).
>
> As a consequence, the Jaxen code, if it were Generified, would have no
> option but to return List<Object> from the method, just like it
> returns Object from the method selectSingleNode();
>
> Object <http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Object.html>
> *selectSingleNode*(Object
> <http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Object.html>
> context) throws JaxenException
> <http://jaxen.codehaus.org/apidocs/org/jaxen/JaxenException.html>
>
> In other words, I have come back around the circle and I believe that
> the method should return exactly List<Object> rather than List<?> or
> List<? extends Object>.
>
> As further considerations against the alternatives:
>
> returning List<? extends Object> implies that the actual returned list
> may be any other specific type as well, e.g. List<String> or
> List<Element> or even something silly like List<System>. This will not
> be the case, the actual returned type will in fact be List<Object> and
> there is no point in making it more obscure by saying List<? extends
> Object> because that actually reduces the meaning.
>
> returning List<?> implies that we have no idea what's in the list, but
> we do.
>
> The logical answer appears to be returning List<Object>. This makes
> the most sense until Jaxen finds a way for the method
> returnSingleNode(Context) to return a type other than Object. Here's
> the Jaxen code:
>
> public Object selectSingleNode(Object node) throws JaxenException {
> List results = selectNodes( node );
> if ( results.isEmpty() ) {
> return null;
> }
> return results.get( 0 );
> }
>
> If Jaxen can be generified to have something like:
>
> public T <T extends Object> selectSingleNode(Object node) throws
> JaxenException {
> List<T> results = selectNodes( node );
> if ( results.isEmpty() ) {
> return null;
> }
> return results.get( 0 );
> }
>
> only then should we consider the alternatives....
>
> On the other hand, the client-side code calling the XPath method is
> going to have to jump through all sorts of instanceof hoops anyways,
> and the return type does not really affect that in any way.
>
> As for Mattias's original claim that List<?> can be cast to
> List<Element> if you know the content will be only Elements, then, I
> believe that lends a certain weight to List<?>, but, is the same not
> true for List<Object>? At some point you will have a compile-time
> warning about unchecked types... unless you do individual casts to
> Element on the contents of the List anyway.
>
> Does this make sense? This whole topic is somewhat interesting, and I
> do see the value in different implementations. There appears to be
> more than one right answer, all with different compromises. At the
> moment I am more in the List<Object> camp but am willing to be
> convinced otherwise....
>
> Rolf
>
> Gregor Zeitlinger wrote:
>> I think List<? extends Object> is more appropriate.
>>
>> It shows that the code has been generified (as opposed to using a
>> plain List).
>> It's similiar to List<?>, but shows that Object is indeed the least
>> common denomiator.
>> _______________________________________________
>> To control your jdom-interest membership:
>> http://www.jdom.org/mailman/options/jdom-interest/youraddr@yourhost.com
>>
>>
>
More information about the jdom-interest
mailing list