JavaRush /مدونة جافا /Random-AR /من 8 إلى 13: نظرة عامة كاملة على إصدارات جافا. الجزء 1

من 8 إلى 13: نظرة عامة كاملة على إصدارات جافا. الجزء 1

نشرت في المجموعة
القطط، مرحبًا بالجميع)) إذن، نحن اليوم في عام 2020، ولم يتبق سوى القليل جدًا حتى إصدار Java 14. من المفترض أن تتوقع صدور الإصدار النهائي في 17 مارس، وسنقوم بتحليل ما هو جديد ومثير للاهتمام هناك بعد ذلك، ولكن اليوم أود تحديث ذاكرتي بشأن الإصدارات السابقة من Java. ما الجديد الذي جلبوه لنا؟ دعونا نلقي نظرة. لنبدأ المراجعة باستخدام Java 8، لأنه لا يزال ملائمًا تمامًا ويستخدم في معظم المشاريع. من 8 إلى 13: نظرة عامة كاملة على إصدارات جافا.  الجزء 1 - 1في السابق، تم إصدار الإصدارات الجديدة كل 3 إلى 5 سنوات، ولكن في الآونة الأخيرة اتخذت Oracle نهجًا مختلفًا - "جافا جديدة كل ستة أشهر". وهكذا، كل ستة أشهر نشهد إصدار الميزات. سواء أكان الأمر جيدًا أم سيئًا، فالجميع يراه بشكل مختلف. على سبيل المثال، لا يعجبني هذا كثيرًا، نظرًا لأن الإصدارات الجديدة لا تحتوي على العديد من الميزات الجديدة، ولكن في نفس الوقت، تنمو الإصدارات مثل الفطر بعد المطر. لقد تراجعت عدة مرات في مشروع باستخدام Java 8، وتم إصدار Java 16 بالفعل (ولكن عندما يتم إصداره نادرًا، تتراكم الميزات الجديدة، وفي النهاية، هذا الحدث الذي طال انتظاره، مثل عطلة: الجميع يناقشون الأشياء الجيدة الجديدة ولا يمكنك تجاوزها). اذا هيا بنا نبدأ!

جافا 8

واجهة وظيفية

ما هذا؟ الواجهة الوظيفية هي واجهة تحتوي على طريقة واحدة (مجردة) غير منفذة. @FunctionalInterface هو تعليق توضيحي اختياري يتم وضعه فوق هذه الواجهة. هناك حاجة للتحقق مما إذا كانت تلبي متطلبات الواجهة الوظيفية (التي تحتوي على طريقة مجردة واحدة فقط). ولكن كما هو الحال دائمًا، لدينا بعض التحذيرات: الأساليب الافتراضية والثابتة لا تندرج تحت هذه المتطلبات. لذلك، يمكن أن يكون هناك العديد من هذه الطرق + طريقة مجردة واحدة، وستكون الواجهة فعالة. قد تحتوي أيضًا على أساليب فئة الكائن التي لا تؤثر على تعريف الواجهة باعتبارها وظيفية. سأضيف بضع كلمات حول الأساليب الافتراضية والثابتة:
  1. تسمح لك الأساليب التي تحتوي على المُعدِّل الافتراضي بإضافة أساليب جديدة إلى الواجهات دون تعطيل تنفيذها الحالي.

    public interface Something {
      default void someMethod {
          System.out.println("Some text......");
      }
    }

    نعم نعم نضيف الطريقة المنفذة إلى الواجهة، وعند تنفيذ هذه الطريقة لا يمكنك تجاوزها بل استخدامها كطريقة موروثة. ولكن إذا نفذت فئة واجهتين باستخدام طريقة معينة، فسيكون لدينا خطأ في الترجمة، وإذا قامت بتنفيذ واجهات ورثت فئة بطريقة مماثلة معينة، فسوف تتداخل طريقة الفئة الأصلية مع طرق الواجهة ولن يعمل الاستثناء.

  2. تعمل الأساليب الثابتة في الواجهة بنفس الطريقة التي تعمل بها الأساليب الثابتة في الفصل الدراسي. لا تنس: لا يمكنك وراثة الأساليب الثابتة ، تمامًا كما لا يمكنك استدعاء طريقة ثابتة من فئة تابعة.

لذا، بضع كلمات أخرى حول الواجهات الوظيفية ودعنا ننتقل. فيما يلي القوائم الرئيسية للمؤسسات المالية (والباقي أنواعها):

    المسند - يأخذ بعض القيمة T كوسيطة، ويعيد القيمة المنطقية.

    مثال:boolean someMethod(T t);

  • المستهلك - يأخذ وسيطة من النوع T، ولا يُرجع أي شيء (باطل).

    مثال:void someMethod(T t);

  • المورد - لا يأخذ أي شيء كمدخل، ولكنه يُرجع بعض القيمة T.

    مثال:T someMethod();

  • الدالة - تأخذ معلمة من النوع T كمدخل، وترجع قيمة من النوع R.

    مثال:R someMethod(T t);

  • UnaryOperator - يأخذ وسيطة T ويعيد قيمة من النوع T.

    مثال:T 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 عند العمل مع التدفقات (كما في أمثلة التدفقات أعلاه). لن نتعمق أكثر من اللازم، نظرًا لأنه يمكننا الغوص عميقًا جدًا، سأترك رابطين حتى يتمكن الرجال الذين ما زالوا منقبين في قلوبهم من التعمق أكثر:

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 عبر :: تأتي مراجع الأساليب في أربعة أنواع:
  1. الرابط للمصمم :

    SomeObject obj = SomeObject::new

  2. مرجع الطريقة الثابتة:

    SomeObject::someStaticMethod

  3. إشارة إلى طريقة غير ثابتة لكائن من نوع معين:

    SomeObject::someMethod

  4. إشارة إلى طريقة عادية (غير ثابتة) لكائن معين

    obj::someMethod

في كثير من الأحيان، يتم استخدام مراجع الطريقة في التدفقات بدلاً من طرق لامدا (الطرق المرجعية أسرع من طرق لامدا، ولكنها أقل جودة في سهولة القراءة).
someList.stream()

        .map(String::toUpperCase)

      .forEach(System.out::println);
بالنسبة لأولئك الذين يريدون المزيد من المعلومات حول الطرق المرجعية:

وقت واجهة برمجة التطبيقات

توجد مكتبة جديدة للعمل مع التواريخ والأوقات - java.time. من 8 إلى 13: نظرة عامة كاملة على إصدارات جافا.  الجزء 1 - 2واجهة برمجة التطبيقات الجديدة تشبه أي واجهة برمجة تطبيقات Joda-Time. أهم أقسام واجهة برمجة التطبيقات هذه هي:
  • LocalDate هو تاريخ محدد، على سبيل المثال - 2010-01-09؛
  • LocalTime - الوقت مع مراعاة المنطقة الزمنية - 19:45:55 (مماثل لـ LocalDate)؛
  • LocalDateTime - التحرير والسرد LocalDate + LocalTime - 2020-01-04 15:37:47؛
  • ZoneId - يمثل المناطق الزمنية؛
  • الساعة - باستخدام هذا النوع يمكنك الوصول إلى الوقت والتاريخ الحاليين.
فيما يلي بعض المقالات المثيرة للاهتمام حقًا حول هذا الموضوع:

خياري

هذه فئة جديدة في الحزمة 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 - وهذا ليس كل شيء. إذا كنت تريد معرفة المزيد، فقد تركت لك هذا:

جافا 9

لذلك، في 21 سبتمبر 2017، شهد العالم JDK 9. يأتي Java 9 مع مجموعة غنية من الميزات. على الرغم من عدم وجود مفاهيم لغة جديدة، إلا أن واجهات برمجة التطبيقات الجديدة وأوامر التشخيص ستكون بالتأكيد موضع اهتمام المطورين. من 8 إلى 13: نظرة عامة كاملة على إصدارات جافا.  الجزء 1 - 4

JShell (REPL - حلقة تقييم القراءة والطباعة)

هذا هو تطبيق Java لوحدة تحكم تفاعلية تُستخدم لاختبار الوظائف واستخدام بنيات مختلفة في وحدة التحكم، مثل الواجهات والفئات والتعدادات والمشغلين وما إلى ذلك. لتشغيل JShell، ما عليك سوى كتابة jshell في الوحدة الطرفية. ثم يمكننا أن نكتب ما يسمح به خيالنا: من 8 إلى 13: نظرة عامة كاملة على إصدارات جافا.  الجزء 1 - 5باستخدام 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) {
  ....
}

نمطية ( بانوراما )

الوحدة عبارة عن مجموعة من الحزم والموارد ذات الصلة بالإضافة إلى ملف واصف الوحدة الجديد. يتم استخدام هذا الأسلوب لتخفيف اقتران التعليمات البرمجية. يعد الاقتران السائب عاملاً رئيسياً لقابلية صيانة التعليمات البرمجية وقابلية التوسعة. يتم تنفيذ النمطية على مستويات مختلفة:
  1. لغة برمجة.
  2. آلة افتراضية.
  3. واجهة برمجة تطبيقات جافا القياسية.
يأتي JDK 9 مزودًا بـ 92 وحدة: يمكننا استخدامها أو إنشاء وحدة خاصة بنا. فيما يلي بعض الروابط لإلقاء نظرة أعمق:

مجموعة غير قابلة للتغيير

في Java 9، أصبح من الممكن إنشاء مجموعة وملؤها بسطر واحد، مع جعلها غير قابلة للتغيير (في السابق، لإنشاء مجموعة غير قابلة للتغيير، كنا بحاجة إلى إنشاء مجموعة، وتعبئتها بالبيانات، واستدعاء طريقة، على سبيل المثال، Collections.unmodifiableList). مثال على هذا الخلق: List someList = List.of("first","second","third");

ابتكارات أخرى:

  • اختياري موسع (تم إضافة طرق جديدة)؛
  • ظهرت واجهات ProcessHandle وProcessHandle للتحكم في إجراءات نظام التشغيل؛
  • G1 - جامع البيانات المهملة الافتراضي؛
  • عميل HTTP مع دعم لكل من بروتوكولات HTTP/2 وWebSocket؛
  • تيار موسع؛
  • تمت إضافة إطار عمل Reactive Streams API (للبرمجة التفاعلية)؛
للحصول على انغماس كامل في Java 9، أنصحك بقراءة:

جافا 10

لذلك، بعد ستة أشهر من إصدار Java 9، في مارس 2018 (أتذكره كما لو كان بالأمس)، ظهر Java 10 على الساحة. من 8 إلى 13: نظرة عامة كاملة على إصدارات جافا.  الجزء 1 - 6

فار

الآن ليس علينا توفير نوع البيانات. نضع علامة على الرسالة على أنها 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 أسرع من نفسه. للحفارين:

الموازي G1

من المؤكد أن مجمع البيانات المهملة G1 رائع، لا شك في ذلك، ولكن لديه أيضًا نقطة ضعف: فهو ينفذ دورة GC كاملة ذات خيط واحد. في الوقت الذي تحتاج فيه إلى كل قوة الأجهزة التي يمكنك حشدها للعثور على الكائنات غير المستخدمة، فإننا نقتصر على موضوع واحد. أصلح Java 10 هذه المشكلة، والآن يعمل GC مع جميع الموارد التي نضيفها إليه (أي يصبح متعدد الخيوط). ولتحقيق ذلك، قام مطورو اللغة بتحسين عزل المصادر الرئيسية عن GC، مما أدى إلى إنشاء واجهة نظيفة وجميلة لـ GC. كان على مطوري هذه الجاذبية، OpenJDK، تنظيف التفريغ في الكود على وجه التحديد ليس فقط لتبسيط إنشاء GCs الجديدة قدر الإمكان، ولكن أيضًا لجعل من الممكن تعطيل GCs غير الضرورية بسرعة من التجميع. أحد المعايير الرئيسية للنجاح هو عدم وجود انخفاض في سرعة التشغيل بعد كل هذه التحسينات. لننظر أيضاً: ابتكارات أخرى:
  1. تم تقديم واجهة نظيفة لجمع البيانات المهملة. يؤدي ذلك إلى تحسين عزل الكود المصدري عن جامعي البيانات المهملة المختلفين، مما يجعل من الممكن دمج المجمعات البديلة بسرعة ودون عناء؛
  2. دمج مصادر JDK في مستودع واحد؛
  3. تلقت المجموعات طريقة جديدة - CopyOf (Collection) ، والتي تقوم بإرجاع نسخة غير قابلة للتغيير من هذه المجموعة؛
  4. يحتوي الاختياري (ومتغيراته) على طريقة جديدة .orElseThrow() ;
  5. من الآن فصاعدًا، تدرك JVMs أنها تعمل في حاوية Docker وستقوم باسترداد التكوين الخاص بالحاوية بدلاً من الاستعلام عن نظام التشغيل نفسه.
فيما يلي بعض المواد الإضافية للحصول على مقدمة أكثر تفصيلاً لـ Java 10: لقد كنت في حيرة من أمري بسبب حقيقة أن بعض إصدارات Java كانت تسمى 1.x. أود أن أكون واضحًا: إصدارات Java السابقة للإصدار التاسع كانت تحتوي ببساطة على نظام تسمية مختلف. على سبيل المثال، يمكن أيضًا تسمية Java 8 بـ 1.8 وJava 5 - 1.5 وما إلى ذلك. والآن نرى أنه مع الانتقال إلى الإصدارات من Java 9، تغير نظام التسمية أيضًا، ولم تعد إصدارات Java مسبوقة بـ 1.x . هذه هي نهاية الجزء الأول: لقد استعرضنا الميزات الجديدة المثيرة للاهتمام في Java 8-10. لنواصل التعرف على الجديد في المنشور القادم .
تعليقات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION