Lew wrote:
>> Maybe because the first example used a raw type on the left of the :, and
>> a parametrized type on the right,
>
> Not sure what you mean by that ?
I take the terminology straight from the Java universe. A raw type is the type
after erasure, when used without a generic parameter. So "List" is a raw type,
"List<Object>" is not.
> One branch is explicitly typed since onhand has type SortedSet<Inventory>. Why
> should the inferencer come up with something different for
> Collections.emptySet() ?
I am not saying that this is the One Right Way, but the reason is that the
Javba language treats raw types at compile time as somewhat equivalent to
"Type<Object>", not "Type<? extends Object>" (i.e., "Type<?>").
> Is it possible that it could produce
> SortedSet<? extends Inventory>
> or something like that ?
Before Sun chose a different approach to raw types it might have been
possible, but Sun did not choose that approach. Furthermore, the style of Java
is mostly about explicit declarations; it does not do a whole lot of type
inference. The inclusion of generics is evidence that Sun favors an explicit
type system over an implicit one.
> I don't see how/why myself, but then I've pretty much given up on working out what the generics stuff does in tricky situations (let
> alone what it /should/ do -- which I suspect is often different).
When you check the rules for the ternary operator, it says that of the types
on both sides of the ':', one must be assignable (upcastable) to the other.
Set<Inventory> and Set<Object> do not fulfill that criterion.
Ergo, Set<Inventory> and the raw type Set do not, either.
Ergo, the ternary expression with a left side of the former type and right
side of the latter does not compile.
When the raw type was changed to one with the parameter <Inventory>, it made
both sides have the same non-raw type, ergo, it compiled.
- Lew
Piotr Kobzda - 28 Feb 2007 08:58 GMT
> Lew wrote:
>>> Maybe because the first example used a raw type on the left of the :,
[quoted text clipped - 6 lines]
> the type after erasure, when used without a generic parameter. So "List"
> is a raw type, "List<Object>" is not.
True. Beside of lack of raw types in "first" example...
In that example type argument inferred for Collections.emptySet() is:
<capture-of ? extends Object> (that's what the compiler is saying in
this case), which implies (regardless of what "capture-of ? extends
Object" is exact equivalent to) that a method's result type is _not a
raw type_.
In general, when the result type of a generic method (which is not
non-static member of erased type) refers to one (or more) of that
method's type variables, that result type is parameterized unless
unchecked conversion was necessary for the method to be applicable. For
such a methods the compiler always infers some type argument according
to the rules described in JLS3 (sections 15.12.2.7 and 15.12.2.8).
>> One branch is explicitly typed since onhand has type
>> SortedSet<Inventory>. Why
[quoted text clipped - 5 lines]
> equivalent to "Type<Object>", not "Type<? extends Object>" (i.e.,
> "Type<?>").
Java treats a raw types more like "Type<?>" (equivalent to "Type<?
extends Object>") than "Type<Object>", but in fact, it's none of them.
"Raw types are closly related to wildcards. Both are based on
existential types. Raw types can be thought of as wildcards whose type
rules are deliberately unsound, to accommodate interaction with legacy
code."
[from 'Discussion' in JLS3 4.8]
>> I don't see how/why myself, but then I've pretty much given up on
>> working out what the generics stuff does in tricky situations (let
[quoted text clipped - 5 lines]
>
> Set<Inventory> and Set<Object> do not fulfill that criterion.
Set<Inventory> and Set<?> do. Which is enough to successfully compile that:
Iterator<? extends Object> getInventoryIterator() {
return (onhand == null ? Collections.emptySet() : onhand)
.iterator();
}
However, the matter here is to guess why the compiler is unable to infer
more specific type argument for ternary conditional expression operand,
when it knows /very well/ both, an expected expression result type and
type of second operand?
Unfortunately, I still can't infer satisfactory answer from thick of JLS
rules. (It appears to me currently that the answer is somewhere around
chapter 15, with all that clear inference rules together with capture
conversion etc., but I can't give precise explanation and I'm close to
give up... :) ).
piotr
Chris Uppal - 28 Feb 2007 13:36 GMT
> Unfortunately, I still can't infer satisfactory answer from thick of JLS
> rules. (It appears to me currently that the answer is somewhere around
> chapter 15, with all that clear inference rules together with capture
> conversion etc., but I can't give precise explanation and I'm close to
> give up... :) ).
I have just taken another look at sections 15.12.2.7, and I /have/ given up !
(Did get one thing out of the exercise, though. Somehow I had been under the
impression that the type inference thing only applied to static generic
methods. I don't know where I got the idea from, but it's wrong. So that's
one less thing that I don't know anout generics ;-)
-- chris
Lew - 01 Mar 2007 06:18 GMT
> (Did get one thing out of the exercise, though. Somehow I had been under the
> impression that the type inference thing only applied to static generic
> methods. I don't know where I got the idea from, but it's wrong. So that's
> one less thing that I don't know anout generics ;-)
That's OK, I got the "raw type equals (roughly) capture-of-Object" thing wrong.
Generics in Java keep me humble. (Not really, but it's not their fault.)
-- Lew