it-swarm.dev

ما هو نوع SAM في جافا؟

عند قراءة مواصفات Java-8 ، ما زلت أرى إشارات إلى "أنواع SAM". لم أتمكن من العثور على شرح واضح لما هو هذا.

ما هو نوع SAM وما هو مثال سيناريو متى يمكن استخدام واحد؟

109
Cody

لتلخيص الرابط الذي نشره جون1 في حالة تعطله ، يشير مصطلح "SAM" إلى "الطريقة المجردة الفردية" ، ويشير "SAM-type" إلى واجهات مثل Runnable ، Callable ، وما إلى ذلك. تعتبر تعبيرات Lambda ، وهي ميزة جديدة في Java 8 ، نوع SAM و يمكن تحويلها بحرية لهم.

على سبيل المثال ، مع واجهة مثل هذا:

public interface Callable<T> {
    public T call();
}

يمكنك التصريح عن Callable باستخدام تعبيرات lambda مثل هذا:

Callable<String> strCallable = () -> "Hello world!";
System.out.println(strCallable.call()); // prints "Hello world!"

تعبيرات لامدا في هذا السياق هي في الغالب مجرد سكر نحوي. تبدو أفضل في التعليمات البرمجية من الفئات المجهولة وتكون أقل تقييدًا في تسمية الطريقة. خذ هذا المثال من الرابط:

class Person { 
    private final String name;
    private final int age;

    public static int compareByAge(Person a, Person b) { ... }

    public static int compareByName(Person a, Person b) { ... }
}

Person[] people = ...
Arrays.sort(people, Person::compareByAge);

يؤدي هذا إلى إنشاء Comparator باستخدام طريقة محددة لا تشترك في نفس اسم Comparator.compare ، وبهذه الطريقة لا يتعين عليك اتباع تسمية واجهة الأساليب ويمكنك الحصول على تخطيات مقارنة متعددة في الفصل الدراسي ، ثم إنشاء المقارنات على تطير عبر تعبيرات امدا.

المضي قدما ...

على مستوى أعمق ، تنفذ Java هذه باستخدام تعليمة invokedynamic bytecode المضافة في Java 7. قلت سابقًا إن إعلان Lambda ينشئ مثيلًا لـ Callable أو Comparable مشابهًا لفئة مجهولة ، لكن هذا ليس بصرامة صحيح. بدلاً من ذلك ، في المرة الأولى التي يتم فيها استدعاء invokedynamic ، تقوم بإنشاء معالج دالة Lambda باستخدام LambdaMetafactory.metafactory method ، ثم تستخدم هذه النسخة المخزنة مؤقتًا في دعوات Lambda المستقبلية . يمكن العثور على مزيد من المعلومات في هذه الإجابة .

هذا النهج معقد ويتضمن حتى رمزًا يمكنه قراءة القيم والمراجع البدائية مباشرةً من ذاكرة المكدس لتمريرها إلى رمز Lambda (على سبيل المثال للالتفاف على الحاجة إلى تخصيص صفيف Object[] لاستدعاء Lambda الخاص بك) ، ولكنه يسمح بتكرار Lambda في المستقبل تطبيق ليحل محل التطبيقات القديمة دون الحاجة إلى القلق بشأن توافق bytecode. إذا غير المهندسون في Oracle تطبيق Lambda الأساسي في إصدار أحدث من JVM ، فإن Lambdas المترجمة على JVM الأقدم سوف تستخدم التنفيذ الأحدث تلقائيًا دون أي تغييرات من جانب المطور.


1 بناء الجملة على الرابط قديم. ألقِ نظرة على Lambda Expressions Java Trail لمشاهدة بناء الجملة الحالي.

115
Brian

واجهات لها بالضبط طريقة مجردة واحدة المعروفة باسم واجهات طريقة مجردة واحدة (SAM واجهات).

عادة ما يطلق عليهم واجهات functinal.

  • Exacly مطلوب أسلوب واحد مجردة
  • يمكن إضافة تعليق توضيحيFunctionalInterface
  • الأساليب الافتراضية ليست مجردة ، لذا يمكننا إضافة أي عدد من الطرق الافتراضية
  • يسمح بإلغاء أساليب فئة الكائن باعتبارها مجردة
  • الواجهات الوظيفية (SAM) مهمة جدًا لكتابة التعبير lambda
  • تتم إضافة العديد من واجهات (SAM) الوظيفية في Java 8 ضمن حزمة Java.util.function

يمكنك قراءة المزيد على ما هي واجهة SAM؟

1
Rupesh Agrawal