اختیاری چیست؟
پارامتر Optional برای حمل اشیاء و فعال کردن مراجع تهی برای مدیریت APIهای مختلف استفاده می شود. بیایید به قطعه کد نگاه کنیم:Coffee coffee = new Coffee();
Integer quantity = coffee.getSugar().getQuantity();
ما یک نمونه قهوه داریم که در آن مقداری شکر از نمونه ای از شی Sugar دریافت می کنیم . اگر فرض کنیم که مقدار کمیت هرگز در سازنده Coffee تنظیم نشده است ، آنگاه coffee.getSugar().getQuantity() یک NullPointerException برمی گرداند . البته همیشه میتوانیم از چکهای تهی خوب قدیمی برای رفع مشکل استفاده کنیم.
Coffee coffee = new Coffee();
Integer quantity = 0;
if (coffee.getSugar() != null) {
quantity = coffee.getSugar().getQuantity();
}
حالا به نظر می رسد همه چیز خوب است. اما هنگام نوشتن کد جاوا، بهتر است از اجرای چک های پوچ خودداری کنیم . بیایید ببینیم چگونه می توان این کار را با استفاده از اختیاری انجام داد.
نحوه ایجاد اختیاری
سه راه برای ایجاد اشیاء اختیاری وجود دارد:-
of(T value) - نمونه سازی از یک شی غیر تهی اختیاری. توجه داشته باشید که استفاده از () برای اشاره به یک شی تهی ، یک NullPointerException ایجاد می کند .
-
ofNullable(T value) - یک مقدار اختیاری برای یک شی ایجاد می کند که می تواند null باشد.
-
vala() - یک نمونه اختیاری ایجاد می کند که نشان دهنده ارجاع به 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() - این متد به شما می گوید که آیا شی Optional حاوی مقدار غیر تهی است یا خیر.
-
get() - مقدار Optional را با مقدار فعلی بازیابی می کند. توجه داشته باشید که فراخوانی get() روی یک اختیاری خالی منجر به NullPointerException می شود .
بهبود بررسی تهی با اختیاری
پس چگونه می توانیم کد بالا را بهبود ببخشیم؟ با Optional می توانیم حضور یک شی را با استفاده از ()isPresent درک کنیم و آن را با استفاده از get() بازیابی کنیم . بیایید با بسته بندی نتیجه () coffee.getSugar با Optional و با استفاده از متد isPresent () شروع کنیم . این به ما کمک می کند تا تعیین کنیم که آیا getSugar() null را برمی گرداند.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();
}
با نگاهی به این مثال، بستهبندی نتیجه ()fafe.getSugar در Optional به نظر نمیرسد ارزشی اضافه کند، بلکه باعث ایجاد دردسر میشود. ما می توانیم نتیجه را با استفاده از توابع مورد علاقه من از کلاس Optional بهبود ببخشیم:
-
نقشه (عملکرد<? super T,? گسترش U> mapper) - مقدار موجود در اختیاری را به تابع ارائه شده نگاشت می کند. اگر پارامتر Optional خالی باشد، map() Optional.empty() را برمی گرداند .
-
orElse(T other) یک نسخه "ویژه" از متد get() است . می تواند مقدار موجود در Optional را دریافت کند. با این حال، در مورد یک اختیاری خالی، این مقدار ارسال شده به متد ()orElse را برمی گرداند .
Coffee coffee = new Coffee();
Integer quantity = Optional.ofNullable(coffee.getSugar())
.map(it -> it.getQuantity())
.orElse(0);
این واقعا عالی است - حداقل من اینطور فکر می کنم. حال، اگر در مورد مقدار خالی، نمیخواهیم مقدار پیشفرض را برگردانیم، باید نوعی استثنا ایجاد کنیم. orElseThrow(Supplier<? extensions X> exclusiveSupplier) مقدار موجود در پارامترهای Optional را برمی گرداند، یا در صورتی که Optional خالی باشد، یک استثنا ایجاد می کند.
Coffee coffee = new Coffee();
Integer quantity = Optional.ofNullable(coffee.getSugar())
.map(it -> it.getQuantity())
.orElseThrow(IllegalArgumentException::new);
همانطور که می بینید، اختیاری چندین مزیت را ارائه می دهد:
- چک های پوچ را چکیده می کند
- یک API برای مدیریت اشیاء پوچ ارائه می کند
- به رویکرد اعلامی اجازه می دهد تا آنچه را که به دست می آید بیان کند
چگونه با اختیاری موثر شویم
در کارم، زمانی که یک متد می تواند حالت «بدون نتیجه» را برگرداند، از Optional به عنوان یک نوع بازگشتی استفاده می کنم. من معمولاً هنگام تعریف انواع برگشتی برای متدها از آن استفاده می کنم.Optional<Coffee> findByName(String name) {
...
}
گاهی اوقات این کار ضروری نیست. به عنوان مثال، اگر من متدی داشته باشم که یک int را برمی گرداند ، مانند getQuantity() در کلاس Sugar ، در آن صورت ممکن است متد 0 را برگرداند اگر نتیجه صفر باشد تا «بدون مقدار» را نشان دهد. اکنون با دانستن این موضوع، میتوانیم فکر کنیم که پارامتر Sugar در کلاس Coffee را میتوان به صورت اختیاری نشان داد. در نگاه اول، این ایده خوبی به نظر می رسد، زیرا از نظر تئوری، شکر نیازی به وجود ندارد. با این حال، اینجا جایی است که می خواهم به زمان عدم استفاده از اختیاری بپردازم. ما باید از استفاده از اختیاری در سناریوهای زیر اجتناب کنیم:
-
به عنوان انواع پارامتر برای POJO ها ، مانند DTO . گزینههای اختیاری قابل سریالسازی نیستند، بنابراین استفاده از آنها در POJO سریالسازی شی را غیرفعال میکند.
-
به عنوان یک استدلال روش. اگر آرگومان متد می تواند null باشد ، پس از منظر کد خالص، ارسال null به پاس اختیاری ارجحیت دارد. علاوه بر این، میتوانید متدهای بارگذاریشده ایجاد کنید تا بهطور انتزاعی به عدم وجود آرگومان متد تهی رسیدگی کنید.
-
برای نشان دادن یک شی مجموعه که گم شده است. مجموعهها میتوانند خالی باشند، بنابراین یک مجموعه خالی ، مانند یک مجموعه یا فهرست خالی ، باید برای نمایش یک مجموعه بدون مقادیر استفاده شود.
GO TO FULL VERSION