English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性。
Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。
使用 Lambda 表达式可以使代码变的更加简洁紧凑。
lambda 表达式的语法格式如下:
(parameters) -> expression 或 (parameters) -> { statements; }
以下是lambda表达式的重要特征:
可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。
Lambda 表达式的简单实例:
// 1. 不需要参数,返回值为 5 () -> 5 // 2. 接收一个参数(数字类型),返回其2倍的值 x -> 2 * x // 3. 接收2个参数(数字),并返回他们的差值 (x, y) -> x – y // 4. 接收2个int型整数,返回他们的和 (int x, int y) -> x + y // 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void) (String s) -> System.out.print(s)
أدخل التالي في ملف Java8Tester.java:
public class Java8Tester { public static void main(String args[]){ Java8Tester tester = new Java8Tester(); // 类型声明 MathOperation addition = (int a, int b) -> a + b; // 不用类型声明 MathOperation subtraction = (a, b) -> a - b; // 大括号中的返回语句 MathOperation multiplication = (int a, int b) -> { return a * b; }; // 没有大括号及返回语句 MathOperation division = (int a, int b) -> a / b; System.out.println("10 + 5 = " + tester.operate(10, 5, addition)); System.out.println("10 - 5 = " + tester.operate(10, 5, subtraction)); System.out.println("10 x 5 = " + tester.operate(10, 5, multiplication)); System.out.println("10 / 5 = " + tester.operate(10, 5, division)); // 不使用括号 GreetingService greetService1 -> System.out.println("Hello " + message); // 使用括号 GreetingService greetService2 = (message) -> System.out.println("Hello " + message); greetService1.sayMessage("w3codebox"); greetService2.sayMessage("Google"); {} interface MathOperation { int operation(int a, int b); {} interface GreetingService { void sayMessage(String message); {} private int operate(int a, int b, MathOperation mathOperation){ return mathOperation.operation(a, b); {} {}
عند تنفيذ السكربت المذكور أعلاه، النتيجة ستكون:
$ javac Java8Tester.java $ java Java8Tester 10 + 5 = 15 10 - 5 = 5 10 x 5 = 50 10 / 5 = 2 مرحبًا w3codebox مرحبًا Google
ينبغي الانتباه إلى النقاط التالية عند استخدام تعبيرات lambda:
يستخدم تعبيرات lambda في الغالب لتحديد أنواع واجهات الأساليب التي تنفذ على مستوى السطر، مثل واجهة الأسلوب البسيط. في هذا المثال، نستخدم أنواعًا مختلفة من تعبيرات lambda لتحديد طرق واجهة MathOperation. ثم نحدد تنفيذ sayMessage.
يخفف تعبيرات lambda من استخدام الطرق المجهولة ويمنح Java قدرات برمجة مبرمجة بالوظائف بسيطة ولكن قوية.
يمكن للتعبيرات الداخلية استخدام المتغيرات المحلية المعلنة كـ final فقط، مما يعني أنه لا يمكن تعديل المتغيرات المحددة في نطاق خارجي داخل التعبيرات الداخلية، وإلا سيكون هناك خطأ في التجميع.
أدخل التالي في ملف Java8Tester.java:
public class Java8Tester { final static String salutation = "Hello! "; public static void main(String args[]){ GreetingService greetService1 -> System.out.println(salutation + message); greetService1.sayMessage("w3codebox"); {} interface GreetingService { void sayMessage(String message); {} {}
عند تنفيذ السكربت المذكور أعلاه، النتيجة ستكون:
$ javac Java8Tester.java $ java Java8Tester مرحبًا! w3codebox
يمكننا أيضًا الوصول إلى المتغيرات المحلية للتعبيرات الداخلية مباشرة:
public class Java8Tester { public static void main(String args[]) { final int num = 1; Converter<Integer, String> s = (param) -> System.out.println(String.valueOf(param + num)); s.convert(2); // نتائج الاطلاق ستكون 3 {} public interface Converter<T1, T2> { void convert(int i); {} {}
مفهوم التعبيرات الداخلية يمكنه استخدام المتغيرات المحلية دون إعلانها كـ final، ولكن يجب ألا يتم تعديلها من قبل الكود التالي (أي بمعنى أنه يملك سياق final)
int num = 1; Converter<Integer, String> s = (param) -> System.out.println(String.valueOf(param + num)); s.convert(2); num = 5; // رسالة الخطأ: يجب أن يكون المتغير المحلي num المحدد في نطاق التجميع محليًا أو بفعالية final
لا يُسمح في التعبيرات Lambda بإنشاء اسم للمعلمة أو المتغير يتطابق مع المتغير المحلي.
String first = ""; Comparator<String> comparator = (first, second) -> Integer.compare(first.length(), second.length()); // سيكون هناك خطأ في التجميع