Actually Java 8 doesn't introduce much that will be detrimental to other JVM languages that interop with Java. The work done on Lambdas helped fix a number of small issues around invokedynamic, MethodHandles , MethodReferences etc - but apart from that it's carry on as normal. That said, there's a whole new bunch of APIs that the other JVM languages could potentially call into now. Which ones they'll use by default or not is up to them.
The largest change impacting interop actually came in with Java 7 - with the invokedynamic bytecode that allows dynamic/late binding calls within the JVM - something that was initially designed for the other languages on the JVM. It's since been very usefully adapted for Lamdbas, so as of Java 8, Java will actually start emitting these bytecodes.
Some languages (JRuby for example) are already heavily using invokedynamic, whilst others (Scala, Groovy et al) are still investigating its use or are in the early stages of patching it in. In theory it makes their dynamic calls almost as performant as existing Java invokestatic calls, as opposed to the myriad of slower workarounds they were forced to use in the past.
Java 9 will bring more challenges for JVM languages with project Jigsaw coming into the platform which will be the beginning of the end for traditionally class loading and classpaths for the JVM. The JVM language folks are pretty aware of this and I expect some sensible collaboration to take place.
Technically speaking, Java does have type inferencing when using generics. With a generic method like
public <T> T foo(T t) {
return t;
}
The compiler will analyze and understand that when you write
// String
foo("bar");
// Integer
foo(new Integer(42));
A String is going to be returned for the first call and an Integer for the second call based on what was input as an argument. You will get the proper compile-time checking as a result. Additionally, in Java 7, one can get some additional type inferencing when instantiating generics like so
Map<String, String> foo = new HashMap<>();
Java is kind enough to fill in the blank angle brackets for us. Now why doesn't Java support type inferencing as a part of variable assignment? At one point, there was an RFE for type inferencing in variable declarations, but this was closed as "Will not fix" because
Humans benefit from the redundancy of the type declaration in two ways.
First, the redundant type serves as valuable documentation - readers do
not have to search for the declaration of getMap() to find out what type
it returns.
Second, the redundancy allows the programmer to declare the intended type,
and thereby benefit from a cross check performed by the compiler.
The contributor who closed this also noted that it just feels "un-java-like", which I am one to agree with. Java's verbosity can be both a blessing and a curse, but it does make the language what it is.
Of course that particular RFE was not the end of that conversation. During Java 7, this feature was again considered, with some test implementations being created, including one by James Gosling himself. Again, this feature was ultimately shot down.
With the release of Java 8, we now get type inference as a part of lambdas as such:
List<String> names = Arrays.asList("Tom", "Dick", "Harry");
Collections.sort(names, (first, second) -> first.compareTo(second));
The Java compiler is able to look at the method Collections#sort(List<T>, Comparator<? super T>)
and then the interface of Comparator#compare(T o1, T o2)
and determine that first
and second
should be a String
thus allowing the programmer to forgo having to restate the type in the lambda expression.
Best Answer
There's a fair bit of incorrect information in ratchet freak's answer and in its comment thread. I'll respond here in an answer, since a comment is too small. Also, since this an answer after all, I'll attempt to answer the original question too. (Note however that I am not an expert on type systems.)
First, the short answers to the original question are Yes and No. Yes, Java 8 will have considerably more type inference than Java 7, and No, there is not a "new" type system in Java 8, although there are some minor changes.
Java 8 will still be statically typed, and it will still have the dichotomy between classes and interfaces. There are no new types such as function types. The type of a lambda is essentially a "functional interface" which is an ordinary interface with a single abstract method.
Interfaces can now have code in the form of default methods, but the model of single-inheritance of classes and multiple inheritance of interfaces remains the same. There are some adjustments, of course, such as rules for method resolution in the presence of default methods, but the fundamentals are unchanged.
Any type that's inferred by type inference could be written out explicitly. To use ratchet freak's example,
is basically sugar for
So sparkleshy's statement "type inference doesn't require any extension of the type system" is basically correct.
But to return to syntactic sugar, I'll repeat my statement that a lambda expression is not syntactic sugar for an anonymous inner class. Ratchet freak stated that a lambda expression is translated into an anonymous inner class instantiation, and Sparkleshy simply reasserted that a lambda is syntactic sugar for an anonymous inner class, but these statements are incorrect. They are probably based on outdated information. Early lambda implementations did implement lambdas this way, but things have changed.
Lambda expressions are semantically different from inner classes, and they are implemented differently from inner classes.
Lambda expressions are semantically different from inner classes in a couple ways. Evaluating a lambda expression need not create a new instance each time. They also have different capture semantics, for example, they capture this differently. In an inner class, this is the inner class instance, whereas in a lambda, this is the enclosing instance. Consider the following:
In a recent JDK 8 lambda build (I used b69), the output will be something like the following:
Furthermore, lambda expressions are implemented completely differently from inner classes. If you compare the disassembled output, you'll see that the inner class code straightforwardly compiles to the creation and call to a constructor of CaptureThis$1, whereas the lambda expression compiles to an invokedynamic instruction that procures a Runnable through means unspecified. For a full explanation of how this works and why, see Brian Goetz' JavaOne 2012 talk Lambda: A Peek Under The Hood.