جافا 8
واجهة وظيفية
ما هذا؟ الواجهة الوظيفية هي واجهة تحتوي على طريقة واحدة (مجردة) غير منفذة. @FunctionalInterface هو تعليق توضيحي اختياري يتم وضعه فوق هذه الواجهة. هناك حاجة للتحقق مما إذا كانت تلبي متطلبات الواجهة الوظيفية (التي تحتوي على طريقة مجردة واحدة فقط). ولكن كما هو الحال دائمًا، لدينا بعض التحذيرات: الأساليب الافتراضية والثابتة لا تندرج تحت هذه المتطلبات. لذلك، يمكن أن يكون هناك العديد من هذه الطرق + طريقة مجردة واحدة، وستكون الواجهة فعالة. قد تحتوي أيضًا على أساليب فئة الكائن التي لا تؤثر على تعريف الواجهة باعتبارها وظيفية. سأضيف بضع كلمات حول الأساليب الافتراضية والثابتة:-
تسمح لك الأساليب التي تحتوي على المُعدِّل الافتراضي بإضافة أساليب جديدة إلى الواجهات دون تعطيل تنفيذها الحالي.
public interface Something { default void someMethod { System.out.println("Some text......"); } }
نعم نعم نضيف الطريقة المنفذة إلى الواجهة، وعند تنفيذ هذه الطريقة لا يمكنك تجاوزها بل استخدامها كطريقة موروثة. ولكن إذا نفذت فئة واجهتين باستخدام طريقة معينة، فسيكون لدينا خطأ في الترجمة، وإذا قامت بتنفيذ واجهات ورثت فئة بطريقة مماثلة معينة، فسوف تتداخل طريقة الفئة الأصلية مع طرق الواجهة ولن يعمل الاستثناء.
-
تعمل الأساليب الثابتة في الواجهة بنفس الطريقة التي تعمل بها الأساليب الثابتة في الفصل الدراسي. لا تنس: لا يمكنك وراثة الأساليب الثابتة ، تمامًا كما لا يمكنك استدعاء طريقة ثابتة من فئة تابعة.
-
المستهلك - يأخذ وسيطة من النوع T، ولا يُرجع أي شيء (باطل).
مثال:
void someMethod(T t);
-
المورد - لا يأخذ أي شيء كمدخل، ولكنه يُرجع بعض القيمة T.
مثال:
T someMethod();
-
الدالة - تأخذ معلمة من النوع T كمدخل، وترجع قيمة من النوع R.
مثال:
R someMethod(T t);
-
UnaryOperator - يأخذ وسيطة T ويعيد قيمة من النوع T.
مثال:
T someMethod(T t);
المسند - يأخذ بعض القيمة T كوسيطة، ويعيد القيمة المنطقية.
مثال:boolean someMethod(T t);
تدفق
التدفقات هي طريقة للتعامل مع هياكل البيانات بأسلوب وظيفي. عادةً ما تكون هذه مجموعات (ولكن يمكنك استخدامها في مواقف أخرى أقل شيوعًا). بلغة أكثر قابلية للفهم، الدفق هو دفق بيانات نعالجه كما لو كنا نعمل مع جميع البيانات في نفس الوقت، وليس القوة الغاشمة، كما هو الحال مع كل منها. دعونا نلقي نظرة على مثال صغير. لنفترض أن لدينا مجموعة من الأرقام التي نريد تصفيتها (أقل من 50)، وزيادة بمقدار 5، وإخراج الأرقام الأربعة الأولى من الأرقام المتبقية إلى وحدة التحكم. كيف كنا نفعل هذا في وقت سابق:List<Integer> list = Arrays.asList(46, 34, 24, 93, 91, 1, 34, 94);
int count = 0;
for (int x : list) {
if (x >= 50) continue;
x += 5;
count++;
if (count > 4) break;
System.out.print(x);
}
لا يبدو أن هناك الكثير من التعليمات البرمجية، والمنطق مربك بعض الشيء بالفعل. دعونا نرى كيف سيبدو باستخدام الدفق:
Stream.of(46, 34, 24, 93, 91, 1, 34, 94)
.filter(x -> x < 50)
.map(x -> x + 5)
.limit(4)
.forEach(System.out::print);
تعمل التدفقات على تبسيط الحياة إلى حد كبير عن طريق تقليل كمية التعليمات البرمجية وجعلها أكثر قابلية للقراءة. بالنسبة لأولئك الذين يرغبون في الخوض في هذا الموضوع بمزيد من التفصيل، إليك مقالة جيدة (أود أن أقول ممتازة) حول هذا الموضوع .
لامدا
ولعل الميزة الأكثر أهمية والتي طال انتظارها هي ظهور لامدا. ما هو لامدا؟ هذه عبارة عن كتلة من التعليمات البرمجية التي يمكن تمريرها إلى أماكن مختلفة بحيث يمكن تنفيذها لاحقًا عدة مرات حسب الحاجة. يبدو مربكا جدا، أليس كذلك؟ ببساطة، باستخدام lambdas، يمكنك تنفيذ طريقة واجهة وظيفية (نوع من تنفيذ فئة مجهولة):Runnable runnable = () -> { System.out.println("I'm running !");};
new Thread(runnable).start();
لقد قمنا بتنفيذ طريقة run() بسرعة وبدون إجراءات روتينية غير ضرورية. ونعم: Runnable هي واجهة وظيفية. أستخدم أيضًا lambdas عند العمل مع التدفقات (كما في أمثلة التدفقات أعلاه). لن نتعمق أكثر من اللازم، نظرًا لأنه يمكننا الغوص عميقًا جدًا، سأترك رابطين حتى يتمكن الرجال الذين ما زالوا منقبين في قلوبهم من التعمق أكثر:
- مقالة عن تعبيرات لامدا في Java 8 على حبري
- مقالة عن تعبيرات لامدا في جافا على مدونة ألكسندر كوساريف
com.foreach
يحتوي Java 8 على أداة foreach جديدة تعمل مع دفق البيانات مثل الدفق. هنا مثال:List<Integer> someList = Arrays.asList(1, 3, 5, 7, 9);
someList.forEach(x -> System.out.println(x));
(مشابه لـ someList.stream().foreach(...))
مرجع الطريقة
الأساليب المرجعية عبارة عن بناء جملة جديد ومفيد مصمم للإشارة إلى الأساليب الموجودة أو مُنشئات فئات أو كائنات Java عبر :: تأتي مراجع الأساليب في أربعة أنواع:-
الرابط للمصمم :
SomeObject obj = SomeObject::new
-
مرجع الطريقة الثابتة:
SomeObject::someStaticMethod
-
إشارة إلى طريقة غير ثابتة لكائن من نوع معين:
SomeObject::someMethod
-
إشارة إلى طريقة عادية (غير ثابتة) لكائن معين
obj::someMethod
someList.stream()
.map(String::toUpperCase)
.forEach(System.out::println);
بالنسبة لأولئك الذين يريدون المزيد من المعلومات حول الطرق المرجعية:
وقت واجهة برمجة التطبيقات
توجد مكتبة جديدة للعمل مع التواريخ والأوقات - java.time. واجهة برمجة التطبيقات الجديدة تشبه أي واجهة برمجة تطبيقات Joda-Time. أهم أقسام واجهة برمجة التطبيقات هذه هي:- LocalDate هو تاريخ محدد، على سبيل المثال - 2010-01-09؛
- LocalTime - الوقت مع مراعاة المنطقة الزمنية - 19:45:55 (مماثل لـ LocalDate)؛
- LocalDateTime - التحرير والسرد LocalDate + LocalTime - 2020-01-04 15:37:47؛
- ZoneId - يمثل المناطق الزمنية؛
- الساعة - باستخدام هذا النوع يمكنك الوصول إلى الوقت والتاريخ الحاليين.
- جافا والوقت: الجزء الأول والثاني عن حبري
- مقدمة إلى واجهة برمجة تطبيقات التاريخ/الوقت في Java 8
خياري
هذه فئة جديدة في الحزمة java.util ، وهي عبارة عن غلاف قيمة تتمثل حيلته في أنه يمكن أن يحتوي أيضًا على قيمة خالية بأمان . الاستلام اختياري: إذا مررنا nullOptional<String> someOptional = Optional.of("Something");
في الاختياري ، فسنحصل على NullPointerException المفضل لدينا . في مثل هذه الحالات يستخدمون: - في هذه الطريقة لا داعي للخوف من القيمة الفارغة. بعد ذلك، قم بإنشاء اختياري فارغ في البداية: للتحقق مما إذا كان فارغًا، استخدم: سيعيد لنا صحيحًا أو خطأ. قم بتنفيذ إجراء معين إذا كانت هناك قيمة، ولا تفعل شيئًا إذا لم تكن هناك قيمة: طريقة عكسية تُرجع القيمة التي تم تمريرها إذا كان الخيار الاختياري فارغًا (نوع من خطة النسخ الاحتياطي): يمكنك الاستمرار لفترة طويلة جدًا ( لحسن الحظ، أضافت شركةOptional طرقًا بكلتا يديه السخيتين)، لكننا لن نتناول هذا الأمر. من الأفضل بالنسبة لي أن أترك رابطين للمبتدئين: Optional<String> someOptional = Optional.ofNullable("Something");
Optional<String> someOptional = Optional.empty();
someOptional.isPresent();
someOptional.ifPresent(System.out::println);
System.out.println(someOptional.orElse("Some default content"));
- جافا اختياري - والد الهوليفار
- اختياري: قطة شرودنغر في Java 8
- فئة اختيارية جديدة في Java 8، وليست حلاً سحريًا لـ NullPointerException
- ميزات Java 8: الدليل النهائي لـ JavaRush - الجزء الأول والثاني ؛
- الجديد في Java 8 على حبري ؛
- أهم 10 ميزات في Java 8 لا يتحدث عنها الناس
- جافا 8 البرنامج التعليمي .
جافا 9
لذلك، في 21 سبتمبر 2017، شهد العالم JDK 9. يأتي Java 9 مع مجموعة غنية من الميزات. على الرغم من عدم وجود مفاهيم لغة جديدة، إلا أن واجهات برمجة التطبيقات الجديدة وأوامر التشخيص ستكون بالتأكيد موضع اهتمام المطورين.JShell (REPL - حلقة تقييم القراءة والطباعة)
هذا هو تطبيق Java لوحدة تحكم تفاعلية تُستخدم لاختبار الوظائف واستخدام بنيات مختلفة في وحدة التحكم، مثل الواجهات والفئات والتعدادات والمشغلين وما إلى ذلك. لتشغيل JShell، ما عليك سوى كتابة jshell في الوحدة الطرفية. ثم يمكننا أن نكتب ما يسمح به خيالنا: باستخدام JShell، يمكنك إنشاء أساليب المستوى الأعلى واستخدامها في نفس الجلسة. ستعمل الأساليب تمامًا مثل الأساليب الثابتة، فيما عدا أنه يمكن حذف الكلمة الأساسية الثابتة.اقرأ المزيد في دليل Java 9 REPL (JShell) .خاص
بدءًا من الإصدار 9 من Java، لدينا الفرصة لاستخدام الأساليب الخاصة في الواجهات (الطرق الافتراضية والثابتة، لأننا ببساطة لا نستطيع تجاوز الآخرين بسبب عدم كفاية الوصول).private static void someMethod(){}
try-with-resources
تمت ترقية القدرة على التعامل مع استثناءات Try-With-Resources:
BufferedReader reader = new BufferedReader(new FileReader("....."));
try (reader2) {
....
}
نمطية ( بانوراما )
الوحدة عبارة عن مجموعة من الحزم والموارد ذات الصلة بالإضافة إلى ملف واصف الوحدة الجديد. يتم استخدام هذا الأسلوب لتخفيف اقتران التعليمات البرمجية. يعد الاقتران السائب عاملاً رئيسياً لقابلية صيانة التعليمات البرمجية وقابلية التوسعة. يتم تنفيذ النمطية على مستويات مختلفة:- لغة برمجة.
- آلة افتراضية.
- واجهة برمجة تطبيقات جافا القياسية.
مجموعة غير قابلة للتغيير
في Java 9، أصبح من الممكن إنشاء مجموعة وملؤها بسطر واحد، مع جعلها غير قابلة للتغيير (في السابق، لإنشاء مجموعة غير قابلة للتغيير، كنا بحاجة إلى إنشاء مجموعة، وتعبئتها بالبيانات، واستدعاء طريقة، على سبيل المثال، Collections.unmodifiableList). مثال على هذا الخلق:List someList = List.of("first","second","third");
ابتكارات أخرى:
- اختياري موسع (تم إضافة طرق جديدة)؛
- ظهرت واجهات ProcessHandle وProcessHandle للتحكم في إجراءات نظام التشغيل؛
- G1 - جامع البيانات المهملة الافتراضي؛
- عميل HTTP مع دعم لكل من بروتوكولات HTTP/2 وWebSocket؛
- تيار موسع؛
- تمت إضافة إطار عمل Reactive Streams API (للبرمجة التفاعلية)؛
- مراجعة جافا 9 على حبري
- جافا 9. ما الجديد؟
- جافا 9: ميزات جديدة
- Java 9 - هل قمت بالترقية حتى الآن؟ لا؟ وليس من الضروري...!؟
- ساندر ماك يتحدث عن الانتقال إلى وحدات Java
جافا 10
لذلك، بعد ستة أشهر من إصدار Java 9، في مارس 2018 (أتذكره كما لو كان بالأمس)، ظهر Java 10 على الساحة.فار
الآن ليس علينا توفير نوع البيانات. نضع علامة على الرسالة على أنها var ويحدد المترجم نوع الرسالة حسب نوع المُهيئ الموجود على اليمين. هذه الميزة متاحة فقط للمتغيرات المحلية التي تحتوي على مُهيئ: لا يمكن استخدامها لوسيطات الطريقة، وأنواع الإرجاع، وما إلى ذلك، نظرًا لعدم وجود مُهيئ لتتمكن من تحديد النوع. مثال var (للنوع String):var message = "Some message…..";
System.out.println(message);
var ليست كلمة أساسية: إنها في الأساس اسم نوع محجوز، تمامًا مثل int . فائدة var عظيمة: إعلانات النوع تستحوذ على الكثير من الاهتمام دون أن تجلب أي فائدة، وهذه الميزة ستوفر الوقت. ولكن في الوقت نفسه، إذا تم الحصول على متغير من سلسلة طويلة من الأساليب، يصبح الكود أقل قابلية للقراءة، لأنه من غير الواضح على الفور نوع الكائن الموجود هناك. مخصص لأولئك الذين يريدون أن يصبحوا أكثر دراية بهذه الوظيفة:
مترجم JIT (GraalVM)
دون مزيد من اللغط، اسمحوا لي أن أذكرك أنه عند تشغيل أمر javac، يتم تجميع تطبيق Java من كود Java إلى رمز JVM bytecode، وهو التمثيل الثنائي للتطبيق. لكن معالج الكمبيوتر العادي لا يمكنه ببساطة تنفيذ كود JVM الثانوي. لكي يعمل برنامج JVM الخاص بك، تحتاج إلى مترجم آخر لهذا الرمز الثانوي، والذي يتم تحويله إلى رمز الجهاز الذي يستطيع المعالج استخدامه بالفعل. بالمقارنة مع javac، يعد هذا المترجم أكثر تعقيدًا، ولكنه ينتج أيضًا كود آلة عالي الجودة. حاليًا، يحتوي OpenJDK على جهاز HotSpot الظاهري، والذي بدوره يحتوي على مترجمين رئيسيين لـ JIT. الأول، C1 ( مترجم العميل )، مصمم للتشغيل بسرعة أعلى، لكن تحسين التعليمات البرمجية يعاني. والثاني هو C2 (مترجم الخادم). تتأثر سرعة التنفيذ، ولكن الكود أكثر تحسينًا. متى يتم استخدام أي واحد؟ يعد C1 رائعًا لتطبيقات سطح المكتب حيث يكون التوقف المؤقت لـ JIT لفترة طويلة غير مرغوب فيه، ويعتبر C2 رائعًا لبرامج الخادم طويلة التشغيل حيث يكون قضاء المزيد من الوقت في الترجمة أمرًا محتملًا تمامًا. التجميع متعدد المستويات يتم عندما يمر التجميع أولاً عبر C1، والنتيجة تمر عبر C2 (يستخدم لمزيد من التحسين). GraalVM هو مشروع تم إنشاؤه ليحل محل HotSpot بالكامل. يمكننا أن نفكر في Graal على أنه العديد من المشاريع ذات الصلة: مترجم JIT جديد لـ HotSpot وجهاز افتراضي متعدد اللغات جديد. خصوصية مترجم JIT هذا هو أنه مكتوب بلغة Java. ميزة مترجم Graal هي السلامة، أي عدم حدوث أعطال، ولكن استثناءات، وليس تسرب الذاكرة. سيكون لدينا أيضًا دعم جيد لـ IDE، وسنكون قادرين على استخدام مصححات الأخطاء أو ملفات التعريف أو غيرها من الأدوات الملائمة. بالإضافة إلى ذلك، قد يكون المترجم مستقلاً عن HotSpot، وسيكون قادرًا على إنشاء نسخة مجمعة من JIT أسرع من نفسه. للحفارين:- الغوص العميق في مترجم Java JIT الجديد
- Graal: كيفية استخدام مترجم JVM JIT الجديد في الحياة الواقعية
- كيف يعمل Graal - مترجم Java JVM JIT
الموازي G1
من المؤكد أن مجمع البيانات المهملة G1 رائع، لا شك في ذلك، ولكن لديه أيضًا نقطة ضعف: فهو ينفذ دورة GC كاملة ذات خيط واحد. في الوقت الذي تحتاج فيه إلى كل قوة الأجهزة التي يمكنك حشدها للعثور على الكائنات غير المستخدمة، فإننا نقتصر على موضوع واحد. أصلح Java 10 هذه المشكلة، والآن يعمل GC مع جميع الموارد التي نضيفها إليه (أي يصبح متعدد الخيوط). ولتحقيق ذلك، قام مطورو اللغة بتحسين عزل المصادر الرئيسية عن GC، مما أدى إلى إنشاء واجهة نظيفة وجميلة لـ GC. كان على مطوري هذه الجاذبية، OpenJDK، تنظيف التفريغ في الكود على وجه التحديد ليس فقط لتبسيط إنشاء GCs الجديدة قدر الإمكان، ولكن أيضًا لجعل من الممكن تعطيل GCs غير الضرورية بسرعة من التجميع. أحد المعايير الرئيسية للنجاح هو عدم وجود انخفاض في سرعة التشغيل بعد كل هذه التحسينات. لننظر أيضاً: ابتكارات أخرى:- تم تقديم واجهة نظيفة لجمع البيانات المهملة. يؤدي ذلك إلى تحسين عزل الكود المصدري عن جامعي البيانات المهملة المختلفين، مما يجعل من الممكن دمج المجمعات البديلة بسرعة ودون عناء؛
- دمج مصادر JDK في مستودع واحد؛
- تلقت المجموعات طريقة جديدة - CopyOf (Collection) ، والتي تقوم بإرجاع نسخة غير قابلة للتغيير من هذه المجموعة؛
- يحتوي الاختياري (ومتغيراته) على طريقة جديدة .orElseThrow() ;
- من الآن فصاعدًا، تدرك JVMs أنها تعمل في حاوية Docker وستقوم باسترداد التكوين الخاص بالحاوية بدلاً من الاستعلام عن نظام التشغيل نفسه.
- دليل جافا 10
- 10 ميزات JDK 10 التي يجب أن يعرفها مطورو Java
- ما الجديد في Java 10: الجزء الأول والثاني
GO TO FULL VERSION