20

I have installed the last JDK 8 ea b114 to test the new language features. However the inference in chained calls seems not to work yet.

If I write:

Iterator<String> it = new ArrayList<>().iterator();

the compiler give me an error.

However inference in argument position works well.

Maybe inference in chained calls will not be inserted?

rgettman
  • 176,041
  • 30
  • 275
  • 357
xdevel2000
  • 20,780
  • 41
  • 129
  • 196
  • You answered your own question there at the end.. – Ben Schulz Nov 12 '13 at 16:17
  • That's strange, I could have sworn that pretty much this situation is what got improved a lot ... – Joachim Sauer Nov 12 '13 at 16:20
  • @JoachimSauer Inference has been thoroughly improved. Method invocations and constructor invocations are now inferred as a whole with the exception of the method receiver. (Btw, I still remember you from the sun forums. Took me a while to figure that out. :D) – Ben Schulz Nov 12 '13 at 17:26

2 Answers2

17

As @Holger said, Java 8 improved contextual inference so that this works_

public static <T> Iterator<T> iter(Iterable<T> i)
{
    return i.iterator();
}

public static void main(String[] args)
{
    Iterator<String> it = iter( new ArrayList<>() );
                \____________________________/
}

It didn't work in Java 7 — the inference on new ArrayList<>() could not depend on context.


It'll be a huge change to the language to do what you want in the question. John Rose started a similar discussion, see http://mail.openjdk.java.net/pipermail/lambda-dev/2013-July/010531.html


Too much inference and too much contextual dependency can be a bad thing. It's not so much that the compiler cannot handle the complexity - it can. It's about whether human programmers can handle it. I am sensing that Java 8 is already at a dangerous level that the codes will be difficult for humans to parse.

Lii
  • 11,553
  • 8
  • 64
  • 88
ZhongYu
  • 19,446
  • 5
  • 33
  • 61
  • 5
    Well, I see that there are corner case like the example in that mailing list where type inference might influence which of overloaded methods to choose. But I really wish that they implement type inference for the 99% of all cases where no overloaded methods exist (like in the `iterator()` example) and forbid it for overloaded methods only, instead of rejecting all cases just because of these 1% (or less) corner cases. – Holger Nov 13 '13 at 11:45
  • 3
    "I am sensing that Java8 is already at a dangerous level that the codes will be difficult for humans to parse." Features of IDEs like method-signature-on-hover (with the inferred generic type information shown) make it a lot easier to parse such things. – JAB Jun 18 '14 at 17:47
  • Iterator a=new ArrayList<>().iterator(); , is getting me compile error in Java 8 though. – Rajeev Akotkar Jun 20 '17 at 03:11
13

The latest specification (Public Review) is available at jcp.org. There is a paragraph in part D which discusses this point.

The receiver in a method invocation, field access, etc. (exp.foo()) is not a poly expression because the target type is unknown—it would be impossible to enumerate every type that has a particular member (foo, in this case). There has been some interest in allowing inference to "chain": in a().b(), passing type information from the invocation of b to the invocation of a. This adds another dimension to the complexity of the inference algorithm, as partial information has to pass in both directions; it only works when the erasure of the return type of a() is fixed for all instantiations (e.g. List). This feature would not fit very well into the poly expression model, since the target type cannot be easily derived.

Ben Schulz
  • 6,101
  • 1
  • 19
  • 15
  • 3
    Sounds like they want to force us again to add obsolete helper methods to our code just to make the compiler happy… :-( – Holger Nov 12 '13 at 16:47
  • @Holger: from all I read about this problem (and similar solutions) "want" is *certainly* not applicable here. But building a highly-complex, probably-broken system that kind-of solves all edge cases (except when it doesn't) usually is not worth it. So they keep it simple (well, simpler, it's *definitely* not simple as it is) so that it actually gets implemented correctly and robustly. – Joachim Sauer Nov 12 '13 at 16:48
  • @Joachim Sauer: may be you don’t know, what I meant. With Java 5 there was the requirement to repeat type signatures at every constructor while wrapping the creation in a simple factory method like ` ArrayList newArrayList() { return new ArrayList(); }` made type inference work without problems: `ArrayList l=newArrayList();`. Even with up to date Java, it’s still the case that you need that ridiculous “diamond operator” for constructors where methods don’t need it. Now with Java 8 it’s the same: wrap like ` Iterator i(Iterable i) { return i.iterator(); }` and it works. – Holger Nov 12 '13 at 16:58
  • 4
    @Holger All I can say is that it's a *very* hard problem. The guys working on the specification and implementation are a smart bunch. They write Java code too and I trust they'd want that to be as pleasant as possible. So they made it less pleasant than imaginable then I doubt it was for lack of trying. – Ben Schulz Nov 12 '13 at 17:20
  • 1
    I have no doubt they are smart and working hard. Still I don’t get why things which can be solved with a generic wrapper method following the always-same pattern ought to be any formal problem. And by the way, the fact that the Java 5 requirement of repeating every type parameter when creating an instance has been removed in Java 7 proves that there never was a real need for it. The logic behind it didn’t change between Java 5 and Java 7. So they *didn’t* try (enough) before. So maybe Java 10 will prove that the reason behind the Java 8 restriction never was an issue? – Holger Nov 12 '13 at 17:57
  • 2
    @Holger Those two are at different levels of difficulty. Constructor is kind of like static method in terms of inference; it's more like an oversight in java5 not to do inference on constructors. Chained method call is a completely different animal. – ZhongYu Nov 12 '13 at 19:35
  • 2
    some related discussions started by john rose - http://mail.openjdk.java.net/pipermail/lambda-dev/2013-July/010531.html – ZhongYu Nov 12 '13 at 19:42
  • Thanks for the link; seems like I'm not alone. – Holger Nov 12 '13 at 21:20
  • Ok. IMHO, it should be better having that inference. However where can I see which goals of a JEP are approved? For example for my question the JEP 101 has been approved only partially... – xdevel2000 Nov 13 '13 at 08:51