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>>>>>>>>>