ماذا تتوقع من Java في 2020؟

2020 على قدم وساق ، دعنا نناقش التغييرات في عالم جافا التي تنتظرنا هذا العام. تسرد هذه المقالة الاتجاهات الرئيسية لـ Java و JDK. وسأكون سعيدًا بإضافات القراء في التعليقات.

إبداء تحفظ على الفور أن المقال هو أكثر من طابع تقصي الحقائق. يمكن العثور على تفاصيل كل موضوع تمت مناقشته على موقع الويب الخاص بالمشروع المقابل أو في المنشورات في مصادر مفتوحة.

صورة

لذا ، لنبدأ. لسوء الحظ ، سيكون عليك على الفور أن تخيب آمال أولئك الذين لا يتابعون دورة إصدار Java كثيرًا ، ولكنهم ينتظرون برنامج دعم طويل (LTS). ننتظر هذا العام الإصدارات مع دورة حياة دعم قصيرة فقط (STS).
الأول سننظر في الإصدار القادم من JDK 14 ، والذي سيتم إصداره في منتصف مارس. في دورة الإصدار هذه ، يتم المطالبة بما يصل إلى 16 من JEPs. ستجد هنا لائحة كاملة:
305:مطابقة الأنماط على سبيل المثال (معاينة)
343:أداة التعبئة والتغليف (الحاضنة)
345:تخصيص الذاكرة NAA-Aware لـ G1
349:تدفق حدث JFR
352:المخازن المؤقتة غير المتطايرة التي تم تعيينها للبايت
358:مفيدة NullPointerExceptions
359:السجلات (معاينة)
361:تبديل التعبيرات (قياسي)
362:إيقاف العمل بمنافذ سولاريس وسبارك
363:قم بإزالة مجمّع البيانات المهملة Sweep Mark Sweep (CMS)
364:ZGC على نظام macOS
365:ZGC على Windows
366:إيقاف العمل بمزيج ParallelScavenge + SerialOld GC
367:إزالة أدوات Pack200 و API
368:كتل النص (المعاينة الثانية)
370:واجهة برمجة تطبيقات الوصول إلى الذاكرة الخارجية (الحاضنة)

تم تغطية العديد من JEPs من هذه القائمة على نطاق واسع في مؤتمر Joker 2019. سأركز على تلك التي تبدو لي الأكثر إثارة للاهتمام.

مطابقة الأنماط على سبيل المثال (معاينة)


سيأتي JEP الطويل أخيرًا في Preview. أعتقد أنك إذا كنت مبرمجًا ممارسًا وكتبت كود Java لسنوات عديدة ، فقد واجهت هذا الألم أكثر من مرة:

if (obj instanceof String) {
    String s = (String) obj;
    System.out.println(s.toUpperCase());
}

إذا كتبت أو كنت تكتب رمزًا أيضًا في Kotlin ، فإن الألم من رؤية رمز Java يكون أسوأ قليلاً. سيقدم لنا المشاركون في مشروع Amber رؤيتهم لمطابقة الأنماط في Java ، والتي يجب أن تقلل هذا الألم. مع ظهور Java 14 ، يمكننا إعادة كتابة المثال على النحو التالي:

if (obj instanceof String s) {
   System.out.println(s.toUpperCase());
}

يبدو أن الإضافة ليست ذات قيمة - فنحن نحفظ سطرًا من التعليمات البرمجية. ولكن لنفترض أننا نريد القيام بما يلي:

if (obj instanceof String) {
    String s = (String) obj;
    if (s.contains(“prefix_”)) {
       return s.toUpperCase();
    }
}
return null;

تبدو ضخمة ، أليس كذلك؟ لنجرب نفس الشيء ، ولكن مع مطابقة الأنماط.

return (obj instanceof String s) && s.contains(“prefix_”) ? s.toUpperCase() : null;

لذا من الواضح أنه سيكون أفضل. ولكن تذكر أن حالة هذه الوظيفة هي معاينة. دعونا نرى ما يتغير بمرور الوقت. بالنسبة لي ، بالتأكيد سيجعل حياتي أفضل.

مفيدة NullPointerExceptions


2020 في الساحة ، وما زلت تكتب بحيث تطير NullPointerExceptions لك؟ لا تقلق ، ربما لست الوحيد. لم يقترح كل من Goetz Lindenmaier و Ralf Schmelter طريقة جديدة للابتعاد عن NullPointerExceptions (اختياري لا يزال معنا) ، لكنهم اقترحوا تحسين عملية تصحيح الأخطاء في التطبيق لفهم بالضبط أين يكمن الصفر. لذا ، دعونا نتخيل أننا نكتب الرمز في الساعة الخامسة ... ليلًا ، بالطبع. وكتبنا هذه الوظيفة:

public String getStreetFromRequest(Request request) {
   return request.getAddress().getStreet().toUpperCase();
}

ليس سيئًا ، لكنهم نسوا تمامًا وضع التعليقات التوضيحيةNullable وNonnull والتحقق من العنوان في الحقول المرسلة. حصلت على NullPointerException. ماذا يقول لنا الاستثناء؟

Exception in thread "main" java.lang.NullPointerException
	at Program.getStreetFromRequest(Program.java:10)
	at Program.main(Program.java:6)

للأسف ، لا نرى سوى صف وفئة وكومة. إلى أين عاد الصفري بالضبط؟ ربما هذا طلب؟ ربما إرجاع getAddress () فارغة؟ أو ربما getStreet ()؟ حسنًا ، تضر سلاسل المكالمات أحيانًا.

يقترح مؤلفو JEP حلاً: عند طرح استثناء ، من المفترض أن يتجاوز المكدس لتحديد مكان الإرجاع الفارغ تمامًا ، ثم عرض اسم المتغيرات / الأساليب. دعنا نجرب Java 14 مع الخيار -XX: + ShowCodeDetailsInExceptionMessages. نبدأ ونختلف قليلا:

Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.toUpperCase()" because the return value of "Address.getStreet()" is null
	at Program.getStreetFromRequest(Program.java:10)
	at Program.main(Program.java:6)

الآن نعلم أن البرمجة الليلية لا تحقق الخير (لكنها تؤدي أحيانًا إلى إكمال المهام في الوقت المحدد) ، وفي برنامجنا نسينا أن العنوان ليس حقلاً مطلوبًا.

السجلات (معاينة)


هل ما زلت تولد رسائل / مستوطنين / يساوي / رمز التجزئة مع الفكرة؟ ثم يأتي هذا JEP لك!
فئات البيانات بعيدة عن المكان الأخير في حياة مطور برامج التطبيق. في كل مرة يتعين علينا إما إنشاء طرق لفئات البيانات باستخدام IDE المفضل لدينا ، أو استخدام العديد من المكونات الإضافية لوقت الترجمة لتوليد الطرق الضرورية ، مثل lombok.

نتيجة لذلك ، لدينا الكثير من التعليمات البرمجية المشابهة لهذا:

public class Request {
    private Address address;

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
       this.address = address;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Request request = (Request) o;
        return Objects.equals(address, request.address);
    }

    @Override
    public int hashCode() {
        return Objects.hash(address);
    }

    @Override
    public String toString() {
        return "Request{" +
                "address=" + address +
                '}';
    }
}

أو مثل:
@Data
@AllArgsConstructor
public class Request {
    private Address address;
}

في Java 14 ، يقترح أعضاء مشروع Amber بنية جديدة لإنشاء فئات البيانات. للقيام بذلك ، استخدم سجل الكلمات الرئيسية الجديد. تختلف بنية التسجيل قليلاً عن وصف الصف أو التعداد ، وهي مشابهة قليلاً لـ Kotlin. يمكن إعادة كتابة الرمز أعلاه على النحو التالي:

public record Request(Address address) {
}

تحتوي جميع حقول السجلات على معدِّلات خاصة ونهائية بشكل افتراضي. السجل نفسه هو فئة نهائية ولا يمكن توريثه من فئة أخرى ، ولكن يمكنه تنفيذ واجهات. في فئات السجلات من المربع نحصل على: طرق getters ، مُنشئ عام ، تكون معلماتها كلها حقول تسجيل في ترتيب الوصف ، يساوي / hashCode و toString. من غير السار: لا يمكننا إضافة حقول إلى السجل ، باستثناء تلك المحددة بعد اسم الفئة. على سبيل المثال ، سيؤدي هذا الرمز إلى حدوث خطأ:

public record Request(Address address) {
   private final String anotherParameter; // compilation error
}

كتل النص (المعاينة الثانية)


تم إصدار كتل نصية كمعاينات سابقة في Java 13. نحن المستخدمين ملتويون ، ودورنا وقدمنا ​​ملاحظات (أعتقد بصدق أنك تستخدم بالفعل Java 13 مع المعاينة). ونتيجة لذلك ، أجرى منشئو جافا تغييرات طفيفة على كتل النص. أولاً ، يمكننا الآن أن نوضح بشكل صريح مكان انتهاء الخط ، من خلال وضع تساوي الخط في خطنا. هنا مثال:

public static void main(String[] args) {
        final var test = """
                This is the long text block with escape string \s
                that is really well done            \s
                """;
        System.out.println(test);
}

الآن قمنا بتعيين جميع المسافات بشكل صريح إلى حرف \ s وسيتم حفظ جميع أحرف المسافة إلى حرف \ s.

ثانيًا ، يمكننا الآن لف الأسطر الطويلة لكتلة نصية دون تلقي \ n أحرف في السطر الأخير. للقيام بذلك ، نحتاج فقط إلى إضافة \ في فاصل الأسطر. كيف تبدو:

public static void main(String[] args) {
        final var test = """
                This is the long text block with escape string \
                that is really well-done functional            
                """;
System.out.println(test);

بعد التنفيذ ، نحصل على السطر التالي: "هذه هي كتلة النص الطويلة بسلسلة الهروب التي تعمل بشكل جيد".

إضافة جيدة ، يبدو لي. إنني أتطلع حقًا إلى ترجمة هذه الوظيفة إلى مستوى قياسي.
من المرجح أن تتم مناقشة جميع الميزات التي استعرضناها على نطاق واسع في المؤتمرات القادمة. تمت مناقشة بعضها بالفعل في Joker 2019. تأكد من الاطلاع على حديث Joker 2019 حول "تطور الميزات في Java 13 وما بعده" بواسطة Cay Horstmann.

وبعض الأشياء الأكثر إثارة للاهتمام.


هناك عنصران مثيران للاهتمام في قائمة JEP في الحاضنة. بادئ ذي بدء ، سيكون لدينا أداة عالمية ستقوم بإنشاء مثبتات لأنظمة تشغيل مختلفة (حسنًا ، أخيرًا ، أريد أن أخبر أولئك الذين رقصوا حول تثبيت البرامج على Windows). سيتمكن Jpacker من إنشاء مثبتات msi / exe لنظام التشغيل Windows وحزم macOS و rpm / deb لنظام Linux. دعونا نرى ما يأتي من هذا ، ولكن في تلك الحالات النادرة عندما قمت بشيء ما لسطح المكتب ، عانيت شخصيا من حقيقة أنني لم يكن لدي أداة منتظمة لتجميع المثبت.

والأكثر واعدة هو واجهة برمجة التطبيقات الجديدة للوصول إلى "الذاكرة الخارجية" ، أي أي نوع من الذاكرة الأصلية أو الثابتة. واجهة برمجة التطبيقات هذه مفيدة بشكل أساسي لمنشئي قاعدة بيانات Java أو لمنشئي الإطارات مثل Netty ، على سبيل المثال. هم ، باستخدام Unsafe و ByteBuffer ، يحسنون الوصول إلى الذاكرة مع الكومة خارج قدر الإمكان.

الإصدار التالي. الفرح والإحباط


في سبتمبر ، ننتظر إصدار دعم قصير الأجل آخر في الرقم 15. قائمة JEPs التي سيتم تضمينها في الإصدار النهائي لا تزال مفتوحة. حتى الآن ، يمكنك رؤية الكثير من التغييرات المختلفة في اللغة نفسها ، في المكتبة القياسية والجهاز الافتراضي.
فيما يلي قائمة المرشحين (يمكن أن تتغير بسرعة ، انظر هنا: bugs.openjdk.java.net/secure/Dashboard.jspa؟selectPageId=19114 ):
111:Additional Unicode Constructs for Regular Expressions
116:Extended Validation SSL Certificates
134:Intuitive Semantics for Nested Reference Objects
152:Crypto Operations with Network HSMs
198:Light-Weight JSON API
218:Generics over Primitive Types
300:Augment Use-Site Variance with Declaration-Site Defaults
301:Enhanced Enums
302:Lambda Leftovers
303:Intrinsics for the LDC and INVOKEDYNAMIC Instructions
306:Restore Always-Strict Floating-Point Semantics
338:Vector API (Incubator)
339:Compiler Intrinsics for Java SE APIs
348:Compiler Intrinsics for Java SE APIs
356:Enhanced Pseudo-Random Number Generators
360:Sealed Types (Preview)
371:Hidden Classes

كما ترى ، لا تزال القائمة لا تحتوي على الكثير من الأشياء المتوقعة. بادئ ذي بدء ، بالنسبة لي هو Project Loom. حظيت فكرة التوازي الهيكلي بشعبية كبيرة في السنوات الأخيرة. تستطيع Coroutines تبسيط مهمة الحوسبة المتوازية التنافسية والتنفيذ غير المتزامن للمهام بشكل كبير. يمكن رؤية أمثلة رائعة لتطبيق هذه الفكرة ، على سبيل المثال ، باللغتين Kotlin (coroutines) و Go (goroutines). تستكشف جافا أيضًا فكرة التوازي الهيكلي ، وهناك بالفعل نتائج أولية. في الوقت الحالي ، يمكنك رؤيتها فقط من خلال تجميع JDK من مستودع المشروع.

مشروع واعد جدًا فالهالا أيضًا لم يسرنا بعد بأي معاينات. تم تقديم تقرير مثير للاهتمام حول هذا المشروع في Joker 2019 ("هل تتطلب Java أنواعًا" مضمنة "؟ نظرة ضيقة لمهندس الأداء في مشروع Valhalla" بواسطة Sergey Kuksenko).

ما هو مدرج في القائمة؟

أول ما يلفت انتباهك هو واجهة برمجة تطبيقات JSON. السؤال الذي يطرح نفسه على الفور - لماذا؟ من الواضح أنه لا توجد إجابة محددة. يقول قسم JEP حول التحفيز أن JSON أصبح شيئًا قياسيًا لخدمات الويب ، والآن حان الوقت لتكييف Java SE للتفاعل مع JSON (على الرغم من وجود الكثير من المكتبات لتحليل JSON الآن). التفسير الأكثر ترجيحًا هو قدرة مطوري البرامج على استخدام واجهة برمجة تطبيقات أساسية صغيرة لتقليل حجم الحزمة دون الحاجة إلى سحب جاكسون الثقيل لأنفسهم. لا أرى أي تفسير آخر ، لأنه لن يكون له حتى قواعد البيانات.

نرى أيضًا عددًا من التحسينات المتعلقة بواجهة برمجة التطبيقات للتشفير. للبدء ، يرغب مطورو JDK في توسيع عملية التحقق من شهادات SSL عن طريق إضافة دعم لشهادات EVSSL. باستخدام واجهة برمجة التطبيقات هذه في Java ، يمكنك تحديد ما إذا كان اتصال SSL موثوقًا به بواسطة شهادة EV (التحقق الممتد). سيتم دعم شهادة EVSSL وفقًا للمبدأ التوجيهي بالكامل. ستتم أيضًا إضافة خوارزمية تشفير جديدة لـ EdDSA وسيتم تحسين التحقق من تشفير HSM.

من أشياء اللغة ، أود أن أشير إلى تنفيذ Generics على البدائيين. يمكن لأي شخص تمت برمجته في لغة C # وتحويله إلى Java ، أن يطرح السؤال على الأرجح ، فلماذا لا يمكنك إجراء أنواع عامة على البدائيين. الجواب بسيط - لا يعمل علم الوراثة إلا مع الكائنات ، والبدائية ليست كائنات ، وعلى وجه الخصوص ، لا ترث فئة كائن. إنها ليست السنة الأولى التي تشن فيها حربًا حول هذه القضية ، ويعود إليها بريان جويتز مرة أخرى. لا يوجد شيء خاص لوصف حتى الآن. المهمة واضحة - لدعم بنيات مثل القائمة. ولكن حتى في الوقت الحالي ، هناك 13 سؤالًا مفتوحًا تحتاج إلى حل قبل تنفيذ هذه الوظيفة. بصراحة ، أتساءل كيف ستنتهي هذه السلسلة.

وآخر شيء أريد أن أتطرق إليه هو الأنواع المختومة. هذه هي الخطوة التالية نحو مطابقة النمط. الأنواع المختومة هي امتداد لغوي يقوم بتنفيذ (المغلق) المختوم ويسمح بالكلمات الرئيسية لفئة أو واجهة.

باستخدام الفئة المختومة ، فإننا نقصر عدد الأحفاد على تلك الفئات المحددة في التصاريح (تقييد صريح) أو في نفس وحدة التصنيف (الملف). وصف مثال لفئة مختومة:

// 
public abstract sealed class Base {
   public static class ChildA extends Base{}
   public static class ChildB extends Base{}
}

// 
public sealed interface BaseInterface permits ChildC, ChildD{
}

//  
public class ChildC implements BaseInterface {
}
//  
public class ChildD implements BaseInterface {
}

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

استنتاج


نظرنا إلى ابتكارات JDK المختلفة هذا العام. بعضهم سيطلق النار ، والبعض الآخر لا. ولكن الأهم من ذلك كله في JDKs الجديدة ، أتوقع تحسينات صغيرة (أو ليست كذلك) تجعل برامجنا أسرع مع كل إصدار مجانًا. وإذا كنت في آخر Joker 2019 وزرت تقرير Tagir Valeev Java 9-14: تحسينات صغيرة ، فعلى الأرجح مثلي ، أعجبك العمل الذي يقوم به المساهمون لتحسين JDK. نتائجها غير مرئية للوهلة الأولى ولا تنعكس في أكثر من JEP ، لكننا نستخدمها كل يوم.

إصدارات Java جيدة لنا جميعًا. استكشف ميزات المنصة الجديدة ، وانتقل إلى المؤتمرات واتبع الاتجاهات.

All Articles