ממשקים פונקציונליים של Java

ממשק פונקציונלי ב-Java הוא ממשק המכיל רק שיטה מופשטת אחת. לממשקים פונקציונליים יכולים להיות מספר שיטות ברירת מחדל או סטטיות אך רק שיטה מופשטת אחת.

מ-Java 8 ואילך ניתן להשתמש בביטויי lambda והפניות לשיטה כדי לייצג את המופע של ממשק פונקציונלי.

דוגמה: שימוש בממשק פונקציונלי עם ביטוי למבדה

Java
   public     class   Geeks     {          public     static     void     main  (  String  []     args  )     {          // Using lambda expression to implement Runnable      new     Thread  (()     ->     System  .  out  .  println  (  'New thread created'  )).  start  ();      }   }   

תְפוּקָה
New thread created  

הֶסבֵּר:

  • התוכנית שלמעלה מדגימה שימוש בביטוי למבדה עם הממשק הפונקציונלי Runnable.
  • ל-Runnable יש שיטה אבסטרקטית אחת run() כך שהוא מתאים כממשק פונקציונלי.
  • Lambda ()-> System.out.println('שרשור חדש נוצר') מגדיר את שיטת run() .
  • new Thread().start() מתחיל שרשור חדש שמבצע את גוף lambda

פֶּתֶק:

א ו ממשק לא פונקציונלי יכול גם להרחיב ממשק פונקציונלי אחר.

@FunctionalInterface ביאור

הערת @FunctionalInterface משמשת כדי להבטיח שלממשק הפונקציונלי לא תהיה יותר משיטה מופשטת אחת. במקרה שיש יותר מתודה מופשטת אחת, המהדר מסמן הודעת 'ביאור @FunctionalInterface בלתי צפוי'. עם זאת אין חובה להשתמש בהערה זו.

פֶּתֶק:

הערת @FunctionalInterface היא אופציונלית, אך זוהי תרגול טוב לשימוש. זה עוזר לתפוס את השגיאה בשלב מוקדם על ידי לוודא שלממשק יש רק שיטה מופשטת אחת.

דוגמה: הגדרת ממשק פונקציונלי עם הערת @FunctionalInterface

Java
   @FunctionalInterface   interface   Square     {      int     calculate  (  int     x  );   }   class   Geeks     {      public     static     void     main  (  String     args  []  )     {      int     a     =     5  ;      // lambda expression to define the calculate method      Square     s     =     (  int     x  )     ->     x     *     x  ;      // parameter passed and return type must be same as defined in the prototype      int     ans     =     s  .  calculate  (  a  );      System  .  out  .  println  (  ans  );      }   }   

תְפוּקָה
25  

הֶסבֵּר :

  • ריבוע הוא ממשק פונקציונלי עם שיטה יחידה calculate(int x).
  • ביטוי למבדה (int x) -> x * x משמש ליישום שיטת החישוב.
  • למדה לוקחת את x כקלט ומחזירה את x * x.

ממשקים פונקציונליים של Java לפני Java 8

לפני Java 8 היינו צריכים ליצור אובייקטים אנונימיים של מחלקה פנימית או ליישם ממשקים אלה. להלן דוגמה לאופן שבו ממשק Runnable יושם לפני הצגת ביטויי למבדה.

דוּגמָה: תוכנית Java להדגמת ממשק פונקציונלי

Java
   class   Geeks     {      public     static     void     main  (  String     args  []  )     {          // create anonymous inner class object      new     Thread  (  new     Runnable  ()     {      @Override     public     void     run  ()      {      System  .  out  .  println  (  'New thread created'  );      }      }).  start  ();      }   }   

תְפוּקָה
New thread created  

ממשקי Java פונקציונליים מובנים

מאז Java SE 1.8 ואילך ישנם ממשקים רבים המומרים לממשקים פונקציונליים. כל הממשקים הללו מסומנים עם @FunctionalInterface. ממשקים אלה הם כדלקמן:

  • ניתן להרצה: ממשק זה מכיל רק את לָרוּץ() שִׁיטָה.
  • בר השוואה: ממשק זה מכיל רק את שיטת compareTo()‎.
  • ActionListener: ממשק זה מכיל רק את שיטת actionPerformed() .
  • ניתן להתקשרות: ממשק זה מכיל רק את השיטה call().

סוגי ממשקים פונקציונליים ב-Java

Java SE 8 כלל ארבעה סוגים עיקריים של ממשקים פונקציונליים שניתן ליישם במספר מצבים כפי שהוזכר להלן:

  1. צַרכָן
  2. לְבַסֵס
  3. פוּנקצִיָה 
  4. סַפָּק

1. צרכן 

ה ממשק צרכנים של הממשק הפונקציונלי הוא זה שמקבל רק ארגומנט אחד או ארגומנט משולש. לממשק הצרכן אין ערך החזרה. זה לא מחזיר כלום. יש גם גרסאות פונקציונליות של הצרכן DoubleConsumer IntConsumer ו LongConsumer . גרסאות אלה מקבלים ערכים פרימיטיביים כטיעונים. 

מלבד גרסאות אלה יש גם גרסה אחת נוספת של ממשק הצרכן המכונה דו-צרכני

תַחבִּיר:

צַרכָן consumer = (value) -> System.out.println(value);

יישום זה של הממשק הפונקציונלי של Java Consumer מדפיס את הערך המועבר כפרמטר להצהרת ההדפסה. יישום זה משתמש בפונקציית Lambda של Java.

2. פרדיקט 

ה ממשק פרדיקטים מייצג פונקציה בעלת ערך בוליאני של ארגומנט אחד. הוא משמש בדרך כלל לפעולות סינון בזרמים. בדיוק כמו לממשק הפונקציונלי של Consumer יש גם לממשק הפונקציונלי של Predicate כמה הרחבות. אלה הם IntPredicate DoublePredicate ו LongPredicate . סוגים אלה של ממשקים פונקציונליים פרדיקטים מקבלים רק סוגי נתונים או ערכים פרימיטיביים כארגומנטים.  

תַחבִּיר: 

פרדיקט ממשק ציבורי {
   מבחן בוליאני (T t);
}

ניתן ליישם את הממשק הפונקציונלי של ג'אווה באמצעות ביטויי Lambda.

לְבַסֵס פרדיקט = (ערך) -> ערך != null;

3. פונקציה

א פוּנקצִיָה הוא סוג של ממשק פונקציונלי ב-Java שמקבל רק ארגומנט בודד ומחזיר ערך לאחר העיבוד הנדרש. גרסאות רבות ושונות של ממשקי הפונקציות הן אינסטרומנטליות ונפוצות בשימוש בטיפוסים פרימיטיביים כמו double int long.

תַחבִּיר:

פוּנקצִיָה function = (ערך) -> ערך * ערך;

  • דו-פונקציה: ה דו-פונקציה קשור באופן מהותי לפונקציה. חוץ מזה צריך שני ארגומנטים ואילו פונקציה מקבלת ארגומנט אחד. 
  • אופרטור אופרטור בינארי ואופרטור בינארי: ישנם גם שני ממשקים פונקציונליים אחרים המכונים בשם מפעיל Unary ו אופרטור בינארי. שניהם מרחיבים את הפונקציה והבי-פונקציה בהתאמה כאשר גם סוג הקלט וגם סוג הפלט זהים.

4. ספק

ה סַפָּק ממשק פונקציונלי הוא גם סוג של ממשק פונקציונלי שאינו לוקח שום קלט או ארגומנט ובכל זאת מחזיר פלט בודד. ההרחבות השונות של הממשק הפונקציונלי של ספק מכילות פונקציות רבות אחרות של ספקים כמו Boolean Supplier DoubleSupplier LongSupplier ו IntSupplier . סוג ההחזר של כל ההתמחויות הנוספות הללו הוא הפרימיטיבים המקבילים שלהם בלבד. 

תַחבִּיר:

סַפָּק ספק = () -> 'שלום עולם!';

דוּגמָה: שימוש בממשק Predicate לסינון מחרוזות

Java
   import     java.util.*  ;   import     java.util.function.Predicate  ;   class   Geeks     {      public     static     void     main  (  String     args  []  )     {          // create a list of strings      List   <  String  >     n     =     Arrays  .  asList  (  'Geek'       'GeeksQuiz'       'g1'       'QA'       'Geek2'  );      // declare the predicate type as string and use lambda expression to create object      Predicate   <  String  >     p     =     (  s  )     ->     s  .  startsWith  (  'G'  );      // Iterate through the list      for     (  String     st     :     n  )     {          // call the test method      if     (  p  .  test  (  st  ))      System  .  out  .  println  (  st  );      }      }   }   

תְפוּקָה
Geek GeeksQuiz Geek2  

טבלת ממשקים פונקציונליים

ממשקים פונקציונליים

תֵאוּר

שִׁיטָה

ניתן להרצה

זה מייצג משימה שניתן לבצע באמצעות שרשור.

void run()

בר השוואה

זה משווה שני אובייקטים להזמנה.

int compareTo(T o)

ActionListener

הוא מטפל באירוע פעולה בתכנות מונחה אירועים.

void actionPerformed(ActionEvent ה)

ניתן להתקשרות

זה מייצג משימה שיכולה להחזיר תוצאה או לזרוק חריגה.

V call() זורק Exception

צַרכָן

הוא מקבל ארגומנט קלט בודד ולא מחזיר תוצאה.

void accept(T t)

לְבַסֵס

הוא מקבל ארגומנט בודד ומחזיר תוצאה בוליאנית.

מבחן בוליאני (T t)

פוּנקצִיָה

הוא מקבל טיעון יחיד ומחזיר תוצאה.

R להחיל (T t)

סַפָּק

זה לא דורש שום טיעון אבל מספק תוצאה.

T get()

BiConsumer

הוא מקבל שני טיעונים ולא מחזיר תוצאה.

void accept(T t U u)

BiPredicate

הוא מקבל שני טיעונים ומחזיר תוצאה בוליאנית.

מבחן בוליאני (T t U u)

BiFunction

הוא מקבל שני טיעונים ומחזיר תוצאה.

R להחיל (T t U u)

UnaryOperator

זהו מקרה מיוחד של Function שבו סוגי הקלט והפלט זהים.

T החל (T t)

BinaryOperator

זהו מקרה מיוחד של BiFunction שבו סוגי הקלט והפלט זהים.

T חל (T t1 T t2)

מאמרים קשורים

  • Java 8
  • Java Lambda Expressions