[jdom-interest] JDom and Java5

Rolf jdom at tuis.net
Sat Feb 23 15:21:37 PST 2008


Hi Mattias.

Thanks for that. I's made me look further in to things than I had 
before. I put together some test code and I see what you mean about 
casting the results. I have been in the habit of coding using eclipse, 
and I set strict compiler warnings and as a result I see lots of 
errors/warnings generated by eclipse. I always try to resolve every 
issue in my code..... and using raw types always produces warnings. This 
would explain my reluctance for returning just plain List. It is a raw 
type and should be avoided. At the same time, I realize now that 
returning List<Object> has it's drawbacks in that you can't cast it to 
anything directly either... although you can actually get away with a 
double-cast .... List<Element> mylist = (List<Element>)(List<?>)(new 
ArrayList<Object>());

By using plain List it introduces compile-time warnings in to JDom. I 
would prefer to avoid that at all costs. It should be the client side 
that encounters the warnings, not the API side.

I am content with returning List<?> or List<? extends Object> for the 
return type. It indicates that the process has been thought through. It 
would also be real interesting to explore turning the entire XPath class 
in to a generic object.... I'm going to play a little bit and get back.

I think there is a fair amount of food for thought. Right now the API 
returns List<?> and this should remove any compile-time issues anyone 
has with the jar, so, for those interested, it is not a hurdle....

Rolf

Mattias Jiderhamn wrote:
> (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