Java 7 of the closure and the merits of Lambda Expressions

Oracle released a few days before the official closure of Java 7 and the first realization of Lambda expressions, which are basically the final version in the style of the official. After reading this realization, my first feeling is "ugly" and, of course not be ruled out because look at the language used to achieve other reason. Later, they thought looked carefully and found that the realization of Java 7 is not without merit, but it seems they feel that certain practices have some problems. In short the whole process is quite interesting and decided to record my thoughts, hope you can come together to discuss attractive.

Lambda expression in Java 7

Lambda expression in Java 7, there are two forms, first of all is the first:

#int() func1 = #()(3); // "func1.()" returns 3
#int(int) func2 = #(int x)(x + 1); // "func2.(3)" returns 4
#int(int, int) func3 = #(int x, int y)(x - y); // "func3.(5, 3)" returns 2

Then the second, meaning and above are equivalent:

#int() func1 = #(){ return 3; };
#int(int) func2 = #(int x){ return x + 1; };
#int(int, int) func3 = #(int x, int y){ return x  –   y; };

If the Lambda's body is "single expression", then you can use the "parentheses", and save the final return keywords; If the body statement in the need to include multiple words, you must use the "braces" and braces can contain multiple statements within, like, like an ordinary way. Both written in C #, there are counterparts, as in "single expression" of the case:

// C#
Func<int> func1 = () => 3; // "func1()" returns 3
Func<int, int> func2 = x => x + 1; // "func2(3)" returns 4
Func<int, int, int> func3 = (x, y) => x - y; // "func3(5, 3)" returns 2

Second, that a number of statements:

// C#
Func<int> func1 = () => { return 3; };
Func<int, int> func2 = x => { return x + 1; };
Func<int, int, int> func3 = (x, y) => { return x  –   y; };

Java and C #, Lambda Expressions by two parts: "argument list" and "expression style", but they have the following differences:

In Java, parameter list and there is no separator between the expression of body, while C # uses "=>" separated.
For the "single expression" of the Lambda is, C # can contain expressions body without the use of parentheses, but Java must use parentheses.

If only a single parameter, then the C # in the argument list can save parentheses, and Java must be retained.

C # on the argument list will be "type inference", which must include full Java parameter type.

These differences that could have big, small can small, but the Java language's design really made me feel more C # for the "ugly", this may be subjective factors, but I think it is not all. For example, if we need an array of user objects in accordance with "age" to sort, written in C #, you can:

// C#
users.Sort(u => u.Age);

In Java, you must write to:

Arrays.sort(users, #(User u)(u.Age));

C # code phrase meaning clear: According to the "u's Age sort", and in Java code, it seems more cumbersome, meaning seems clear enough. Anders in the design of C # syntax, when great emphasis on "declarative" code is evident. In addition, I do not understand why not choose the parameters of Java type inference, in my opinion it is very important to write elegant code (on this point, "Why Java Sucks and C # Rocks" series, will be discussed in more detail). But Java is not no "inference", for example, from the above code snippet can be learned, Java return value for the Lambda expression type inference is carried out. In fact, Java has also concluded the "unusual type", there will be more discussion of this point later.

Of course, Java can be "out of nothing" in the definition of "anonymous function type" (which is relatively closer to the point and VB.NET), without the same need as the C # based on specific "delegate type", even more flexible.

SAM type of support and closure

SAM stands for Single Abstract Method, if a type SAM type, it means that it 1) is an abstract type (ie interface or abstract class), and 2) there is only one method is not implemented. For example, a Java interface, is a SAM type:

public interface Func<T, R> {
  R invoke(T arg);

So we will be able to:

Func<int, int>[] array = new Func<int, int>[10];
for (int i = 0; i < array.length; i++) {
  final int temp = i;
  array[i] = #(int x)(x + temp);

Can see, we use Lambda expression to create the Func interface instance, this is not available in C #. This point is particularly important, because in Java class library there are already many types of code that uses the SAM. But I found that, in some manner using the SAM seems to have some "ambiguity", for example this code:

public class MyClass {
  public int hashCode() {
    throw new RuntimeException();

  public void MyMethod() {
    Func<int, int> func = #(int x)(x * hashCode());
    int r = func.invoke(5); // throw or not?

Here we override (override) the MyClass the hashCode method, it throws RuntimeException, then the call func1 MyMethod defined object will throw an exception? The answer is no, because in the Lambda expression, the hidden "this reference to" represent the func objects, calling it the hashCode will not throw RuntimeException. So, if we are to call the hashCode MyClass how to do? It somewhat troublesome:

Func<int, int> func = #(int x)(x * MyClass.this.hashCode());

   But from another perspective on the sample code  :

public class MyClass { 

  public int n = 3; 

  public void MyMethod() {
    Func<int, int> func = #(int x)(x + n);
    int r = func.invoke(5); // 8

Func object because there is no n, where n is therefore defined in the n MyClass class members of the. Therefore, Java does not capture the closure is not literally following in the members only in the SAM type of case, the literal context (lexical scope) members of the priority targets will be lower than the abstract type members.

Overall, the type of support for SAM, I think there is merit in Java, only I still think that this would create confusion because I have the impression in the Lambda expressions in other languages seem to capture literally below ( Of course they may have no SAM support). However, how in the "ambiguity" and "elegant" to make a balance between that I do not find satisfactory answers.

Mishaps: Checked Exception

Other common equivalent Java language has a special feature, that is Checked Exception. Checked Exception means that each method to indicate what they will throw exception type (RuntimeException and its subclasses excluded), which is part of the contract method, the compiler will force programmers to write code to meet the unusual contract. Such as the definition of a library in such a way:

public void myMethod() throws AException, BException

Which is marked on the back of myMethod throws may have been thrown. So if we write a method to call myMethod, it could be:

public void myMethodCaller() throws AException {
  try {
  } catch (BException ex) {
    throw new AException(ex);

When we write a method call to method A to B, we use either method A, B throw try ... catch to capture the method, or the signature of the method is marked A, "will throw the same exception." If the above myMethodCaller way, it in-house and the BException exception, but only the external thrown AException. Java will be strictly limited the use of this method Abnormal library information.

Checked Exception is a controversial feature. It is for the preparation of high-quality code is important because the situation in which methods throw exceptions are in fact part of the contract (not just signature or return value of the problem), should be strictly observed, can not upgrade the library destroyed Otherwise, compatibility issues will arise. For example, your interest in MSDN in the document, you will see the description of anomalies, but it is the "Document" record, but Java is mandatory in the code; However, from another point of view, Checked Exception become very cumbersome to write code, which led to a situation that many people writing code, custom exceptions are all RuntimeException (because no mark), each method throws Exception has been the (so the code in the do not try ... catch up), then basically useless Checked Exception characteristics, in addition to trouble any good other than the few.

I have often said before: a feature if you want to be widely accepted, then it must be good enough. Now if Scala and Grovvy such as the Java language designed to have abandoned Checked Exception, this can be considered confirmed Checked Exception from the side of embarrassing situations it.

The Checked Exception Lambda or closure for now, in my opinion more like a Mishap. Why? Give you an example, if there is such a map method, an array can be mapped into another type of array:

public R[] map(T[] array, Func<T, R> mapper) { ... }

Well, such a demand: Given a string array, save the file name, its standard request path. Apparently, we can write:

map(files, #(String f)(new File(f).getCanonicalPath())

But in fact, do not compile. Why? Method for getCanonicalPath throws IOException, we must explicitly call the use of try ... catch for processing. So how to write this code? Really can not write. If the words do not Checked Exception (such as C #), we can also do this (for the first thrown IOException):

try {
  map(files, #(String f)(new File(f).getCanonicalPath())
catch (IOException ex) {

But before that if we are to write "beautiful" and written, you can not use the Func <T, R> must be like this interface type:

public interface FuncThrowsIOException<T, R> {
  R invoke(T arg) throws IOException;

Or is this "anonymous function type":

#String(String)(throws IOException) // toCanonicalPath = #(String f)(new File(f).getCanonicalPath())

However, as Lambda and closure of the common scenes, such as map, filter, fold and other "functional" element, it is impossible to a specific "exception type" designed - the exception type changing, is it also use throws Exception to be "unified handling" it? Although already supporting Java exception type of "inference" but Checked Exception is on the applicability of Lambda and closures had a significant impact.

Therefore, I think Checked Exception is a "Mishap."


Java, the closure of Lambda and some features, such as parameters of "generalization":

#boolean(Integer) f = #(Number n)(n.intValue() > 0);

As Integer Number is the base class, so we can use to accept Integer Number to construct an anonymous function parameter type. As the sample less, I do not know the specific use of this feature and the significance of the scene - but I guess, in Java, could allow it to do so:

#boolean(Number) f = #(Number n)(n.intValue() > 0);
#boolean(Integer) f1 = f; // cast implicitly or explicitly

There are also some features, such as MethodHandle type of transformation, I have no particular view of the.


分类:Java 时间:2010-06-18 人气:201
blog comments powered by Disqus


  • Oracle decode function and sign function is not equivalent with realization decode 2011-07-08

    - Example: the number of less than 0 is displayed as a negative select decode (sign (num), -1, 'negtive', num) from dual;

  • oracle listener can not start monitoring solution 2010-03-29

    Often encounter the situation can not start oracle listener feeling very strange, more experienced, some of the reasons summed up gradually. First, after installing the oracle time, in a network state, and the next start time is off network state, wi ...

  • ORACLE PL / SQL AND analyse fuction 2010-04-22

    PLSQL Development notes and summary ***************************************** The basic structure of PLSQL ***************************************** Basic data type variables 1. Basic data types Number numeric Int integer Pls_integer integer type, resulti

  • The most complete oracle notes 2010-12-08

    Oracle SQL day1 Oracle SQL (Oracle 9i A, DataBase Save data to the table in the form of performance data Second, SQL SQL (structure query language Structured Query Language), is operating in an object relational database DDL (data definition la

  • js closure on 2009-04-01

    Understanding of JavaScript closures To become advanced JavaScript programmers, it is necessary to understand the closure. In this paper, ECMA 262 specification explain the closure of the internal working mechanism for JavaScript programmers understanding

  • oracle remote connection methods 2010-04-25

    Server-side, open the listener and oracle database instance Client: Select the Net Configuration Assistant procedure in the "Local Net Service Name" -> specifies the service name (Note: this service to connect remote host star as the ide ...

  • Oracle Database issue summary (part of the switched network) 2010-06-03

    1.Oracle basic types of databases that when you create a data table in the database, you need to define the type of all fields in the table. ORACLE There are many kinds of data types to meet your needs. Some data types are divided into: character, number,

  • oracle modify the archive mode 2010-06-11

    First check the database of existing models can use the following statement select name, log_mode from v $ database; Can also use the following statement archive log list; (the method requires as sysdba) For non-archive mode to archive mode of the da

  • Oracle external table using the five restriction 2010-08-13

    Oracle external table is like a view in the database can be the same as trying to query and other operations. This attempt to allow users to run any external data SQL statements, without first loading the external table data into the database. Extern

iOS 开发

Android 开发

Python 开发



PHP 开发

Ruby 开发






Javascript 开发

.NET 开发



Copyright (C), All Rights Reserved. 版权所有 黔ICP备15002463号-1

processed in 0.061 (s). 14 q(s)