From: Timbo on
Hi everyone,

A question about type inferencing in Sun's compiler: I have the
following factory method for creating an empty list:

public static <E> List<E> list()
{
return new java.util.ArrayList<E>();
}

Now, consider the following method that takes a list of String:

private void useStringList(List<String> stringList)
{ ... }

I can invoke "useStringList" on an empty list as follows:

List<String> strList = Factory.list();
useStringList(strList);

The compiler will infer from "List<String> strList" that the
return type of "Factory.list()" is "List<String>" in this
instance. However, take the following snippet:

useStringList(Factory.list());

The compiler complains that "useStringList" cannot be applied to
"List<Object>". Why is it that it can infer the type in the former
example, but not the latter? I am aware that I can write:

useStringList(Factory.<String>list());

but this is a bit comvoluted when compared to just
"Factory.list()", and there is certainly enough information to
infer the type.

Thanks,
Tim
From: Oliver Wong on

"Timbo" <timbo(a)noreply.invalid> wrote in message
news:dfpr24$4if$1(a)kinder.server.csc.liv.ac.uk...
> Hi everyone,
>
> A question about type inferencing in Sun's compiler: I have the following
> factory method for creating an empty list:
>
> public static <E> List<E> list()
> {
> return new java.util.ArrayList<E>();
> }
>
> Now, consider the following method that takes a list of String:
>
> private void useStringList(List<String> stringList)
> { ... }
>
> I can invoke "useStringList" on an empty list as follows:
>
> List<String> strList = Factory.list();
> useStringList(strList);
>
> The compiler will infer from "List<String> strList" that the return type
> of "Factory.list()" is "List<String>" in this instance. However, take the
> following snippet:
>
> useStringList(Factory.list());
>
> The compiler complains that "useStringList" cannot be applied to
> "List<Object>". Why is it that it can infer the type in the former
> example, but not the latter? I am aware that I can write:
>
> useStringList(Factory.<String>list());
>
> but this is a bit comvoluted when compared to just "Factory.list()", and
> there is certainly enough information to infer the type.

Because of method overloading, you must know the types of your
parameters before you can choose which method to call. In the line
"useStringList(Factory.list());" the compiler doesn't know yet which
useStringList is going to be called until it knows the type of
Factory.list(). So it first evaluates the type of Factory.list(). Since
there is no context information saying otherwise, it determines
Factor.list() to return an object of type List<Object>. Now it tries to find
a method matching the signature useStringList(List<Object>) and finds none,
hence the error.

- Oliver


From: Roedy Green on
On Thu, 08 Sep 2005 18:58:14 GMT, "Oliver Wong" <owong(a)castortech.com>
wrote or quoted :

>Because of method overloading, you must know the types of your
>parameters before you can choose which method to call. In the line
>"useStringList(Factory.list());" the compiler doesn't know yet which
>useStringList is going to be called until it knows the type of
>Factory.list(). So it first evaluates the type of Factory.list(). Since
>there is no context information saying otherwise, it determines
>Factor.list() to return an object of type List<Object>. Now it tries to find
>a method matching the signature useStringList(List<Object>) and finds none,
>hence the error.

does not the parameter overload matching proceed totally ignoring
genericity?
--
Canadian Mind Products, Roedy Green.
http://mindprod.com Again taking new Java programming contracts.
From: John C. Bollinger on
Roedy Green wrote:
> does not the parameter overload matching proceed totally ignoring
> genericity?

Pretty much yes. As I understand it, method signatures are not
differentiated one from another by genericity, which means among other
things that you cannot have overloaded versions of a method that differ
only in their type parameters. This is an implication of type erasure.
The compiler checks type parameter compatibility after determining the
appropriate method to invoke (without consideration of type parameters).
Oliver's [elided] explanation of why type is not inferred for method
arguments may nevertheless be about right, but it seems to me that it
calls out an issue with the compiler architecture rather than anything
inherent in the type system. I wonder whether it's really just a
shortcut to limit the intelligence that the compiler needs to exercise.

--
John Bollinger
jobollin(a)indiana.edu
From: Chris Uppal on
John C. Bollinger wrote:

> Oliver's [elided] explanation of why type is not inferred for method
> arguments may nevertheless be about right, but it seems to me that it
> calls out an issue with the compiler architecture rather than anything
> inherent in the type system. I wonder whether it's really just a
> shortcut to limit the intelligence that the compiler needs to exercise.

Another place where it seems that the compiler /should/ be able to infer types,
but does not is in conditional code. E.g. (from memory)

List<String> stringList = null;
if (...)
stringList = Factory.list();
else
stringList = ASimilarFactory.list();

is OK, but:

List<String> stringList = (...)
? Factory.list()
: ASimilarFactory.list();

is not.

Personally, I'm going off this type inference fast[*] (and I wasn't too keen on
it in the first place), but if we are going to have it, then at least it should
be done properly...

-- chris

([*] It seems obfuscatory, and is also IMO contrary to the spririt of a
language in which
byte b = ...;
byte lowNybble = b & 0x0F;
is not allowed.
)