ما هو اختياري؟
يتم استخدام المعلمة الاختيارية لحمل الكائنات وتمكين المراجع الخالية من التعامل معها بواسطة واجهات برمجة التطبيقات المختلفة. دعونا نلقي نظرة على مقتطف الكود:Coffee coffee = new Coffee();
Integer quantity = coffee.getSugar().getQuantity();
لدينا مثيل Coffee حيث نحصل على كمية من السكر من مثيل كائن Sugar . إذا افترضنا أن قيمة الكمية لم يتم تعيينها مطلقًا في مُنشئ القهوة ، فإن Coffee.getSugar().getQuantity() ستُرجع NullPointerException . بالطبع، يمكننا دائمًا استخدام عمليات التحقق القديمة الجيدة من القيمة الفارغة لإصلاح المشكلة.
Coffee coffee = new Coffee();
Integer quantity = 0;
if (coffee.getSugar() != null) {
quantity = coffee.getSugar().getQuantity();
}
الآن يبدو أن كل شيء على ما يرام. ولكن عند كتابة كود Java، من الأفضل أن نتجنب تنفيذ عمليات التحقق من القيمة الفارغة . دعونا نرى كيف يمكن القيام بذلك باستخدام اختياري.
كيفية إنشاء اختياري
هناك ثلاث طرق لإنشاء كائنات اختيارية:-
of(قيمة T) — إنشاء كائن اختياري غير فارغ. انتبه إلى أن استخدام of() للإشارة إلى كائن فارغ سيؤدي إلى ظهور NullPointerException .
-
ofNullable(قيمة T) - ينشئ قيمة اختيارية لكائن يمكن أن يكون خاليًا.
-
()empty - ينشئ مثيلًا اختياريًا يمثل مرجعًا إلى null .
// пример использования Optional.of(T Value)
String name = "foo";
Optional<String> stringExample = Optional.of(name)
// пример использования Optional.ofNullable(T Value)
Integer age = null;
Optional<Integer> integerExample= Optional.ofNullable(age)
// пример использования Optional.empty()
Optional<Object> emptyExample = Optional.empty();
لذلك لديك كائن اختياري. الآن دعونا نلقي نظرة على الطريقتين الرئيسيتين للاختياري:
-
isPresent() - تخبرك هذه الطريقة ما إذا كان الكائن الاختياري يحتوي على قيمة غير فارغة.
-
get() - يسترد قيمة الاختياري بالقيمة الحالية. انتبه إلى أن استدعاء get() على خيار اختياري فارغ سيؤدي إلى NullPointerException .
تحسين التحقق من القيمة الخالية مع الاختياري
فكيف يمكننا تحسين الكود أعلاه؟ باستخدام الخيار الاختياري، يمكننا فهم وجود كائن باستخدام isPresent() واسترجاعه باستخدام get() . لنبدأ بتعبئة نتيجة Coffee.getSugar() مع اختياري واستخدام طريقة isPresent() . سيساعدنا هذا في تحديد ما إذا كان getSugar() يُرجع قيمة فارغة.Coffee coffee = new Coffee();
Optional<String> sugar = Optional.ofNullable(coffee.getSugar());
int quantity = 0;
if (sugar.isPresent()) {
Sugar sugar = sugar.get();
int quantity = sugar.getQuantity();
}
بالنظر إلى هذا المثال، يبدو أن تعبئة نتيجة Coffee.getSugar() في اختياري لا يضيف أي قيمة، بل يزيد من المتاعب. يمكننا تحسين النتيجة باستخدام ما أعتبره وظائفي المفضلة من الفئة الاختيارية:
-
Map(Function<? super T,? Extends U> Mapper) - يقوم بتعيين القيمة الموجودة في الاختياري للوظيفة المتوفرة. إذا كانت المعلمة الاختيارية فارغة، فستُرجع الخريطة() اختياريًا.فارغة() .
-
orElse(Tother) هو إصدار "خاص" من طريقة get() . يمكنه الحصول على القيمة الموجودة في الاختياري. ومع ذلك، في حالة وجود خيار اختياري فارغ، فسيؤدي ذلك إلى إرجاع القيمة التي تم تمريرها إلى طريقة orElse() .
Coffee coffee = new Coffee();
Integer quantity = Optional.ofNullable(coffee.getSugar())
.map(it -> it.getQuantity())
.orElse(0);
هذا رائع حقًا - على الأقل أعتقد ذلك. الآن، إذا كنا لا نريد إرجاع القيمة الافتراضية في حالة القيمة الفارغة، فسنحتاج إلى طرح نوع من الاستثناء. orElseThrow(Supplier<? Extends X> ExceptionSupplier) يُرجع القيمة الموجودة في المعلمات الاختيارية، أو يطرح استثناءً إذا كان الاختياري فارغًا.
Coffee coffee = new Coffee();
Integer quantity = Optional.ofNullable(coffee.getSugar())
.map(it -> it.getQuantity())
.orElseThrow(IllegalArgumentException::new);
كما ترون، يوفر الاختياري العديد من المزايا:
- ملخصات الشيكات فارغة
- يوفر واجهة برمجة التطبيقات (API) للتعامل مع الكائنات الفارغة
- يسمح للنهج التصريحي بالتعبير عما يتم تحقيقه
كيف تصبح فعالاً مع الاختياري
في عملي، أستخدم اختياري كنوع إرجاع عندما تتمكن إحدى الطرق من إرجاع حالة "لا توجد نتيجة". عادةً ما أستخدمه عند تحديد أنواع الإرجاع للطرق.Optional<Coffee> findByName(String name) {
...
}
في بعض الأحيان هذا ليس ضروريا. على سبيل المثال، إذا كان لدي طريقة تُرجع int ، مثل getQuantity() في فئة Sugar ، فقد تُرجع الطريقة 0 إذا كانت النتيجة فارغة لتمثل "بلا كمية". الآن، بعد أن عرفنا ذلك، يمكننا أن نعتقد أنه يمكن تمثيل معلمة السكر في فئة القهوة على أنها اختيارية. للوهلة الأولى، تبدو هذه فكرة جيدة لأنه من الناحية النظرية، لا يلزم وجود السكر في القهوة. ومع ذلك، هذا هو المكان الذي أود أن أتناوله عند عدم استخدام الاختياري. يجب أن نتجنب استخدام الاختياري في السيناريوهات التالية:
-
كأنواع معلمات لـ POJOs ، مثل DTOs . الاختيارات غير قابلة للتسلسل، لذا فإن استخدامها في POJO يعطل إمكانية تسلسل الكائن.
-
كحجة الأسلوب. إذا كان من الممكن أن تكون وسيطة الطريقة null ، فمن منظور التعليمات البرمجية الخالصة، يظل تمرير null أفضل من تمرير اختياري. بالإضافة إلى ذلك، يمكنك إنشاء أساليب مثقلة للتعامل بشكل تجريدي مع غياب وسيطة الأسلوب الفارغة.
-
لتمثيل كائن المجموعة المفقود. يمكن أن تكون المجموعات فارغة، لذلك يجب استخدام مجموعة فارغة ، مثل مجموعة أو قائمة فارغة ، لتمثيل مجموعة بدون قيم.
GO TO FULL VERSION