کلاس Optional چیست و چرا باید از آن استفاده کنیم؟
کلاسی است که در جاوا ۸ معرفی شده و هدف ان جلوگیری از خطای معروف nullpointerexception میباشد(هرچند گویا به طور کامل از چنین خطایی نتوانسته جلوگیری کند)
میتوان گفت بیشتر ابزاری ست برای راحت تر چک کردن مقادیر تهی و راحت تر گریختن از خطای nullpointerexception
بیگمان هرکس که با جاوا کد زده باشد با خطای nullpointerexception اشنا میباشد.
فرض کنید کلاسی به نام Person داریم و در ان یک فیلد به نام name و یک گتر برای آن داریم:
public class Person {
private String name;
public String getName() {
return name;
}
}
حال در کلاس main برنامه ی خود یک متد داریم به این صورت:(فرض کنید این متد بر اساس یکسری عملیات به مقدار null رسیده است..مثلا Person را از دیتابیس خوانده و هیچ مقداری پیدا نکرده است)
public static Person getPerson() {
return null;
}
طبعا هنگامی که در main چنین خط کدی را بنویسیم :
public static void main(String[] args) {
getPerson().getName();
}
به خطای nullpointerexception برمیخوریم.
حال راه حل جاوا هشت برای گریز از این خطا چیست؟
ابتدا توضیحاتی اندک ولی کارامد درمورد متد های کلاس Optional میدهیم:
کلاس اپشنال از دیزاین پترن Factory استفاده میکند(اجازه ی ساخت شی با کلید new از ان را نداریم):
Optional.empty();
Optional.of(T t);
Optional.ofNullable();
متد اول به جای همان مثال بالا که null برگشت دادیم استفاده میشود.
متد دوم یک مقدار میپذیرد با این شرط که تهی نباشد و متد سوم میتواند مقداری تهی نیز بپذیرد.
حال مثال اول را اینگونه بازنویسی میکنیم:
در اغاز بایستی نوع بازگشتی متد را از جنس Optionalتعریف کنیم:
public static Optional<Person> getPerson() {
return Optional.empty();
}
حال در متد main متد getPerson را call میکنیم:
public static void main(String[] args) {
Optional<Person> op=getPerson();
System.out.println(op);
}
خواهیم دید که دیگر خبری از ارور nullpointerexception نیست بلکه چنین چیزی در خروجی مشاهده میکنیم:
Optional.empty
سایر متد های سودمند کلاس اپشنال:
orElse(T t);
اگر مقدار وجود داشت...مقدار Tرا برگشت میدهد وگرنه مقداری که در ورودی متد داده اید را برگشت میدهد(دیگر مقدار null درکار نخواهد بود)
isPresent();
اگر مقداری داخل اپشنال بود true برگشت میدهد اگر نبود false
get();
اگر مقدار وجود داشت برگشت میدهد و اگر نبود nosuchelementexception برگشت میدهد(و بازهم خبری از ارور null نیست)
ifPresent(Consumer<? super T> consumer)
اگر مقدار وجود داشت عملیات مورد نظرمان انجام شود
ifPresentOrElse(Consumer<? super T> consumer,Runnable run)
اگر مقدار وجود داشت عملیات مورد نظر انجام شود و اگر تهی بود متد run از اینترفیس runnable صدا زده میشود
و بسیار متد های سودمند دیگر
توجه داشته باشید runnable در بالا ربطی به ترد ندارد و صرفا بخاطر متد run از ان استفاده شده است