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 { 
  @Override 
  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 { 
    myMethod(); 
  } 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."

Other

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.

Source: http://blog.zhaojie.me/2010/06/first-version-of-lambda-and-closures-in-java-7.html
  • del.icio.us
  • StumbleUpon
  • Digg
  • TwitThis
  • Mixx
  • Technorati
  • Facebook
  • NewsVine
  • Reddit
  • Google
  • LinkedIn
  • YahooMyWeb

Related Posts of Java 7 of the closure and the merits of Lambda Expressions

  • Hibernate configuration parameters hibernate.hbm2ddl.auto

    Hibernate in the configuration file: <properties> <property name="hibernate.hbm2ddl.auto" value="create" /> </ properties> Parameter Description: validate load hibernate, the authentication to create a database t ...

  • spring + hibernate + oracle9i to read and write CLOB

    Database-driven update classes12-9i.jar Hibernate modify the configuration of the following code <bean/> <bean Lazy-init="true"> <property name="nativeJdbcExtractor"> <ref local="nativejdbcExtractor"/>

  • Build flex + spring + blazeds + hibernate application

    Build flex + spring + blazeds + hibernate application First, set up the project blazeds 1, will blazeds.war extract to a directory, such as: myflex /; 2, set up java works were such as: MyFlex, in the orientation of selection create project from exis ...

  • Hibernate connection pool configuration

    Hibernate connection pool configuration <! - Jdbc -> <property name="connection.driver_class"> oracle.jdbc.driver.OracleDriver </ property> <property name="connection.url"> jdbc: oracle: thin: @ 10.203.14.132:15

  • hibernate generic generic DAO

    package org.lzpeng.dao; import java.io.Serializable; import java.util.List; import org.hibernate.Criteria; import org.hibernate.Query; import org.hibernate.criterion.Criterion; import org.springside.modules.orm.hibernate.Page; /** * * @version 2009-1-10 *

  • Struts2 + hibernate + spring problem user log in

    dao layer services layer action jsp <tr> <td align="center"> <b> user name: </ b> </ td> <td> <s: textfield name = "czyNumber" cssClass = "textstyle" theme = "simple" size = &q

  • Hibernate secondary cache

    Hibernate cache: 2-bit cache, also known as process-level cache or SessionFactory level cache, secondary cache can be shared by all of the session Cache configuration and the use of: Will echcache.xml (the document code in hibernate package directory ...

  • Hibernate's lazy strategy

    hibernate Lazy strategy can be used in: <class> tag, it can be true / false Tags can <PROPERTY> values true / false type of necessary tools to enhance <set> <list> can tag values true / false / extra <many-to-one> <on ...

blog comments powered by Disqus
Recent
Recent Entries
Tag Cloud
Random Entries