الكلية الجامعية للعلوم التطبيقيةبرمجة 1
English
المحاضرة 11 · 100 دقيقة

الدوال: تعريفها واستدعاؤها

كيف نعطي مجموعة من الأوامر اسمًا، ونستخدمها كلما احتجنا إليها؟

في نهاية هذه المحاضرة ستكون قادرًا على

  1. تشرح لماذا نكتب الدوال: تقليل التكرار وتسمية الأفكار
  2. تعرّف دالة من نوع void وتستدعيها
  3. تميّز بين المعامل والوسيط، وتمرّر عدة وسائط بالترتيب الصحيح
  4. تكتب دالة تُرجع قيمة، وتستخدم هذه القيمة داخل تعبير
  5. تتتبّع الدخول إلى الدالة والخروج منها في المتتبّع، وتقرأ مكدس الاستدعاءات
  6. تصلح أخطاء المترجم الشائعة في الدوال
محتويات المحاضرة
  1. الدالة تنهي التكرار وتعطي الفكرة اسمًا
  2. أنت تستدعي الدوال منذ المحاضرة الأولى
  3. نعرّف الدالة مرة واحدة ونستدعيها باسمها
  4. المعامل صندوق في الدالة، والوسيط قيمة تضعها فيه
  5. المعامل يجعل الدالة الواحدة تصلح لحالات كثيرة
  6. الوسائط تُسند إلى المعاملات بالترتيب، لا بالاسم
  7. الأمر return يعيد قيمة إلى من استدعى الدالة
  8. الاستدعاء يصلح داخل أي تعبير يقبل قيمته
  9. الدالة التي تُرجع boolean تصبح شرطًا مقروءًا
  10. في الدالة عدة أوامر return، وينفذ منها واحد فقط
  11. الدالة إما أن تنجز عملًا أو تُرجع جوابًا
  12. كل استدعاء يحصل على إطار خاص وصناديق خاصة به
  13. الدالة التي تعد بقيمة يجب أن تُرجعها في كل مسار
  14. الاستدعاء يجب أن يطابق التعريف في الاسم والعدد والنوع
  15. أسئلة المراجعة
الجزء الأول: تعريف الدالة واستدعاؤها

الدالة تنهي التكرار وتعطي الفكرة اسمًا

قلنا في المحاضرة الأولى إن الدالة مجموعة أوامر لها اسم. انظر إلى البرنامج التالي لتعرف لماذا نحتاج إليها: الحلقة نفسها مكتوبة ثلاث مرات.

كم سطرًا ستعدّل؟

شغّل البرنامج. ثم اجعل كل خط من 10 نجوم بدلًا من 20، وعدّ الأماكن التي اضطررت إلى تعديلها.

public class Report {
    public static void main(String[] args) {
        for (int i = 0; i < 20; i++) {
            System.out.print("*");
        }
        System.out.println();

        System.out.println("Sales report");

        for (int i = 0; i < 20; i++) {
            System.out.print("*");
        }
        System.out.println();

        System.out.println("Total: 150");

        for (int i = 0; i < 20; i++) {
            System.out.print("*");
        }
        System.out.println();
    }
}
الناتج
********************
Sales report
********************
Total: 150
********************
تكتبها مرة واحدة

تكتب الأوامر في مكان واحد، وتستخدمها حيثما شئت. وإذا أردت تعديلها عدّلت مكانًا واحدًا.

تسمّي الفكرة

الاسم printStars يخبرك بما يحدث دون أن تقرأ الحلقة.

أنت تستدعي الدوال منذ المحاضرة الأولى

كتب غيرك هذه الدوال، وأنت تستدعيها باسمها دون أن تعرف تفاصيلها. اليوم ستكتب دوالك بنفسك. لاحظ الأقواس بعد كل اسم: فيها نعطي الدالة ما تحتاج إليه.

الاستدعاءما نعطيهاما تفعله أو تُرجعه
System.out.println("Hi")نصًاتطبعه، ولا تُرجع شيئًا
input.nextInt()لا شيءتُرجع العدد الذي كتبه المستخدم
Math.pow(2, 3)عددينتُرجع 2 مرفوعًا للقوة 3

الدالة Math.pow تُرجع قيمة، ونحن نطبعها. ماذا يظهر؟

public class PowerCall {
    public static void main(String[] args) {
        System.out.println(Math.pow(2, 3));
    }
}
أظهر الناتج
الناتج
8.0

لماذا؟ Math.pow تُرجع دائمًا قيمة من نوع double، ولهذا يظهر 8.0 لا 8. الدالة هي التي تحدد نوع ما تُرجعه، وسنحدده اليوم بأنفسنا.

نعرّف الدالة مرة واحدة ونستدعيها باسمها

الجزءمعناه
staticمطلوبة الآن في كل دالة نكتبها، وسنشرحها في مساق لاحق.
voidلا تُرجع هذه الدالة شيئًا
greetاسم الدالة، بنمط camelCase مثل المتغيرات
()قائمة المعاملات، وهي هنا فارغة
{ ... }جسم الدالة: الأوامر التي تنفذها

أول دالة لك

الدالة greet تقع داخل الصنف وخارج main. شغّل البرنامج، ثم أضف استدعاءً ثالثًا وتوقّع الناتج قبل التشغيل.

public class Greeting {
    static void greet() {
        System.out.println("Hello!");
        System.out.println("Welcome to Java.");
    }

    public static void main(String[] args) {
        greet();
        greet();
    }
}
الناتج
Hello!
Welcome to Java.
Hello!
Welcome to Java.

عرّفنا دالة لكن هل استدعيناها؟

public class NotCalled {
    static void sayBye() {
        System.out.println("Bye");
    }

    public static void main(String[] args) {
        System.out.println("Start");
        System.out.println("End");
    }
}
أظهر الناتج
الناتج
Start
End

لماذا؟ يبدأ التشغيل دائمًا من main، أيًا كان ترتيب الدوال في الملف. والتعريف لا ينفذ شيئًا؛ لا تعمل الدالة إلا إذا استُدعيت.

المعامل صندوق في الدالة، والوسيط قيمة تضعها فيه

المعامل (parameter)

متغير نصرّح عنه بين قوسي التعريف. هنا name.

static void greet(String name)
الوسيط (argument)

القيمة التي نكتبها عند الاستدعاء. هنا "Sara".

greet("Sara");
name"Sara"String

تحية لكل اسم

اضغط «تتبّع سطرًا سطرًا»، ثم «دخول» عند كل استدعاء، وراقب الصندوق name يحمل قيمة مختلفة كل مرة. أضف استدعاءً باسمك.

public class GreetByName {
    static void greet(String name) {
        System.out.println("Hello, " + name + "!");
    }

    public static void main(String[] args) {
        greet("Sara");
        greet("Omar");
    }
}
الناتج
Hello, Sara!
Hello, Omar!

في static void show(int age) والاستدعاء show(19)، ما المعامل وما الوسيط؟

المعامل يجعل الدالة الواحدة تصلح لحالات كثيرة

لنعد إلى التقرير الذي بدأنا به. الحلقة أصبحت في مكان واحد، والطول صار وسيطًا نغيّره كما نشاء.

سطر من النجوم

توقّع الناتج ثم شغّل. غيّر الطول إلى 10 في كل الخطوط، ثم قارن عدد ما عدّلته بما عدّلته في البرنامج الأول.

public class StarReport {
    static void printStars(int count) {
        for (int i = 0; i < count; i++) {
            System.out.print("*");
        }
        System.out.println();
    }

    public static void main(String[] args) {
        int width = 20;
        printStars(width);
        System.out.println("Sales report");
        printStars(width);
        System.out.println("Total: 150");
        printStars(width);
    }
}
الناتج
********************
Sales report
********************
Total: 150
********************

مثلث من النجوم

اقرأ عددًا صحيحًا rows، ثم اطبع مثلثًا: السطر الأول نجمة واحدة، والثاني نجمتان، وهكذا حتى rows. استدعِ printStars داخل حلقة. لا تطبع أي رسالة طلب.

import java.util.Scanner;

public class StarTriangle {
    static void printStars(int count) {
        for (int i = 0; i < count; i++) {
            System.out.print("*");
        }
        System.out.println();
    }

    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        int rows = input.nextInt();
        // Call printStars inside a loop here

    }
}
stdin
3
الناتج المتوقع
*
**
***
تلميح 1

عدّاد الحلقة يبدأ من 1 وينتهي عند rows.

تلميح 2

الوسيط هو عدّاد الحلقة نفسه: printStars(i).

الحل
import java.util.Scanner;

public class StarTriangle {
    static void printStars(int count) {
        for (int i = 0; i < count; i++) {
            System.out.print("*");
        }
        System.out.println();
    }

    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        int rows = input.nextInt();
        for (int i = 1; i <= rows; i++) {
            printStars(i);
        }
    }
}

الوسائط تُسند إلى المعاملات بالترتيب، لا بالاسم

معاملان من نوعين مختلفين

نفصل بين المعاملات بفاصلة. اطبع خطًا من 8 علامات =. ثم بدّل ترتيب الوسيطين في أحد الاستدعاءين، واقرأ رسالة المترجم.

public class RepeatSymbol {
    static void printLine(char symbol, int count) {
        for (int i = 0; i < count; i++) {
            System.out.print(symbol);
        }
        System.out.println();
    }

    public static void main(String[] args) {
        printLine('#', 5);
        printLine('-', 3);
    }
}
الناتج
#####
---

الدالة نفسها والوسيطان نفسهما، لكن بترتيب مختلف. ماذا يطبع؟

public class ArgumentOrder {
    static void divide(int top, int bottom) {
        System.out.println(top / bottom);
    }

    public static void main(String[] args) {
        int top = 2;
        int bottom = 10;
        divide(10, 2);
        divide(top, bottom);
    }
}
أظهر الناتج
الناتج
5
0

لماذا؟ الوسيط الأول يذهب إلى المعامل الأول دائمًا. في الاستدعاء الثاني top تحمل 2 وbottom تحمل 10، والقسمة بين عددين صحيحين تحذف الكسر فيكون الناتج 0.

الجزء الثاني: الدوال التي تُرجع قيمة

الأمر return يعيد قيمة إلى من استدعى الدالة

نكتب نوع القيمة المُرجَعة مكان void. وعند الاستدعاء تحل القيمة المُرجَعة محل الاستدعاء، كما تفعل Math.pow. هذا هو الإرجاع.

في التعريف

int تعني أن الدالة تعد بإرجاع عدد صحيح.

static int max(int a, int b)
عند الاستدعاء

تُخزَّن القيمة المُرجَعة في متغير لتُستخدم لاحقًا.

int bigger = max(3, 7);

الأكبر من عددين

اضغط «تتبّع سطرًا سطرًا»، ثم «دخول» عند سطر max. لاحظ أن الصندوق bigger يظهر في main بعد الخروج من الدالة. اختبر عددين متساويين.

public class MaxOfTwo {
    static int max(int a, int b) {
        if (a > b) {
            return a;
        } else {
            return b;
        }
    }

    public static void main(String[] args) {
        int bigger = max(3, 7);
        System.out.println(bigger);
        System.out.println(max(10, 4));
    }
}
الناتج
7
10

الأمر return ينهي الدالة فورًا. ماذا يطبع البرنامج؟

public class ReturnStops {
    static String check(int n) {
        if (n > 0) {
            return "positive";
        }
        return "not positive";
    }

    public static void main(String[] args) {
        System.out.println(check(5));
        System.out.println(check(0));
    }
}
أظهر الناتج
الناتج
positive
not positive

لماذا؟ مع 5 يتحقق الشرط، فينتهي التنفيذ عند أول return ولا يصل إلى الثاني. ومع 0 لا يتحقق الشرط، فيصل إلى return الأخير. كل استدعاء يُرجع قيمة واحدة فقط.

الاستدعاء يصلح داخل أي تعبير يقبل قيمته

المساحة في تعبيرات مختلفة

نستخدم القيمة المُرجَعة في إسناد، وفي عملية حسابية، وفي شرط، وفي دمج نص. أضف دالة perimeter تحسب محيط المستطيل واطبعه.

public class RectangleArea {
    static double area(double width, double height) {
        return width * height;
    }

    public static void main(String[] args) {
        double first = area(3, 4);
        double total = first + area(2.5, 2);
        System.out.println(total);
        if (area(1, 1) < first) {
            System.out.println("The first one is bigger");
        }
        System.out.println("Area: " + area(5, 5));
    }
}
الناتج
17.0
The first one is bigger
Area: 25.0

كل استدعاء يحل محله ما يُرجعه. ماذا يطبع؟

public class ReturnInExpression {
    static int square(int x) {
        return x * x;
    }

    public static void main(String[] args) {
        int total = square(3) + square(4);
        System.out.println(total);
        System.out.println(square(square(2)));
    }
}
أظهر الناتج
الناتج
25
16

لماذا؟ 9 + 16 = 25. وفي السطر الأخير يُنفَّذ الاستدعاء الداخلي أولًا فيعطي 4، ثم يصبح وسيطًا للخارجي فيعطي 16.

مساحة المثلث

اكتب الدالة triangleArea التي تأخذ base وheight من نوع double وتُرجع المساحة. يقرأ main العددين، ثم يطبع Area: متبوعًا بالناتج.

import java.util.Scanner;

public class TriangleArea {
    // Write the triangleArea method here

    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        double base = input.nextDouble();
        double height = input.nextDouble();
        // Call triangleArea and print the result

    }
}
stdin
5
3
الناتج المتوقع
Area: 7.5
تلميح 1

المساحة نصف القاعدة في الارتفاع. احذر 1 / 2، فهي تساوي 0 في Java.

تلميح 2

جسم الدالة سطر واحد: return base * height / 2;

الحل
import java.util.Scanner;

public class TriangleArea {
    static double triangleArea(double base, double height) {
        return base * height / 2;
    }

    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        double base = input.nextDouble();
        double height = input.nextDouble();
        System.out.println("Area: " + triangleArea(base, height));
    }
}

الدالة التي تُرجع boolean تصبح شرطًا مقروءًا

هل العدد زوجي؟

اقرأ الشرط بصوت عالٍ: «إذا كان 7 زوجيًا». نكتب الاسم كسؤال يبدأ بـ is، ونُرجع نتيجة المقارنة مباشرة. اكتب دالة isPositive بالطريقة نفسها وجرّبها.

public class EvenCheck {
    static boolean isEven(int n) {
        return n % 2 == 0;
    }

    public static void main(String[] args) {
        System.out.println(isEven(4));
        if (isEven(7)) {
            System.out.println("7 is even");
        } else {
            System.out.println("7 is odd");
        }
    }
}
الناتج
true
7 is odd

عدّ الأعداد الزوجية

اقرأ عددًا n، ثم استخدم الدالة isEven داخل حلقة لتعدّ الأعداد الزوجية من 1 إلى n. اطبع Evens: متبوعًا بالعدد.

import java.util.Scanner;

public class CountEvens {
    static boolean isEven(int n) {
        return n % 2 == 0;
    }

    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        int n = input.nextInt();
        // Count the even numbers from 1 to n, then print the result

    }
}
stdin
6
الناتج المتوقع
Evens: 3
تلميح 1

صرّح عن عدّاد count يبدأ من 0 قبل الحلقة.

تلميح 2

داخل الحلقة: if (isEven(i)) { count++; }.

الحل
import java.util.Scanner;

public class CountEvens {
    static boolean isEven(int n) {
        return n % 2 == 0;
    }

    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        int n = input.nextInt();
        int count = 0;
        for (int i = 1; i <= n; i++) {
            if (isEven(i)) {
                count++;
            }
        }
        System.out.println("Evens: " + count);
    }
}

في الدالة عدة أوامر return، وينفذ منها واحد فقط

حرف التقدير

استخدم «تتبّع سطرًا سطرًا» و«دخول» مع الاستدعاء gradeLetter(85)، ولاحظ أين تنتهي الدالة. ثم غيّر الوسيط إلى 90 و89، وتوقّع الحرف في كل مرة قبل التشغيل.

public class GradeLetter {
    static char gradeLetter(int score) {
        if (score >= 90) {
            return 'A';
        } else if (score >= 80) {
            return 'B';
        } else if (score >= 70) {
            return 'C';
        } else if (score >= 60) {
            return 'D';
        } else {
            return 'F';
        }
    }

    public static void main(String[] args) {
        System.out.println(gradeLetter(85));
        System.out.println(gradeLetter(59));
    }
}
الناتج
B
F

سعر التذكرة

اكتب الدالة ticketPrice التي تأخذ العمر وتُرجع السعر: أقل من 6 سنوات 0، ومن 6 إلى 17 5، و18 فأكثر 10. يطبع main الطلب Age: ، ثم يقرأ العمر، ثم يطبع Price: والسعر على السطر نفسه.

import java.util.Scanner;

public class TicketPrice {
    static int ticketPrice(int age) {
        // Replace this line with the rules
        return 0;
    }

    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.print("Age: ");
        int age = input.nextInt();
        // Print "Price: " and the result of ticketPrice

    }
}
stdin
5
الناتج المتوقع
Age: Price: 0
تلميح 1

ابدأ بأصغر الأعمار: if (age < 6)، ثم else if (age < 18).

تلميح 2

لا يظهر ما يكتبه المستخدم في ناتج الاختبار، ولذلك يبدو الطلب والنتيجة متصلين.

الحل
import java.util.Scanner;

public class TicketPrice {
    static int ticketPrice(int age) {
        if (age < 6) {
            return 0;
        } else if (age < 18) {
            return 5;
        } else {
            return 10;
        }
    }

    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.print("Age: ");
        int age = input.nextInt();
        System.out.println("Price: " + ticketPrice(age));
    }
}

الدالة إما أن تنجز عملًا أو تُرجع جوابًا

وجه المقارنةvoidتُرجع قيمة
مثالprintStars(5);int m = max(3, 7);
كيف تنتهيتصل إلى }تنفذ return مع قيمة
أين نستدعيهافي سطر مستقل فقطداخل تعبير عادةً؛ وفي سطر مستقل تضيع قيمتها

الدالة twice تحسب وتُرجع. هل تغيّرت x؟

public class DiscardReturn {
    static int twice(int n) {
        return n * 2;
    }

    public static void main(String[] args) {
        int x = 5;
        twice(x);
        System.out.println(x);
        System.out.println(twice(x));
    }
}
أظهر الناتج
الناتج
5
10

لماذا؟ السطر twice(x); يحسب 10 ثم تضيع القيمة لأن أحدًا لم يستخدمها، وx تبقى 5. وفي السطر الأخير تستقبل println القيمة المُرجَعة فتطبعها.

لا شيء لتطبعه

الدالة printStars تطبع بنفسها ولا تُرجع شيئًا، ومع ذلك وضعناها داخل println. أصلح سطر الاستدعاء.

public class VoidPrint {
    static void printStars(int count) {
        for (int i = 0; i < count; i++) {
            System.out.print("*");
        }
        System.out.println();
    }

    public static void main(String[] args) {
        System.out.println(printStars(3));
    }
}
رسالة المترجم'void' type not allowed here
أظهر التصحيح
public class VoidPrint {
    static void printStars(int count) {
        for (int i = 0; i < count; i++) {
            System.out.print("*");
        }
        System.out.println();
    }

    public static void main(String[] args) {
        printStars(3);
    }
}
الناتج
***

لماذا؟ تحتاج println إلى قيمة تطبعها، ودالة void لا تعطي قيمة. فاستدعِها في سطر مستقل.

تريد دالة تحسب معدل الطالب ليستخدمه main في شرط. ما النوع المناسب لما تُرجعه؟

الجزء الثالث: تتبّع التنفيذ وإصلاح الأخطاء

كل استدعاء يحصل على إطار خاص وصناديق خاصة به

عند الاستدعاء ينتقل التنفيذ إلى الدالة وينتظر المستدعي، وعند انتهائها يعود إليه ليكمل. ويحتفظ البرنامج بسلسلة الاستدعاءات الجارية في مكدس الاستدعاءات (call stack): لكل استدعاء إطار (frame) فيه متغيراته، وأحدث إطار في الأعلى.

ادخل واخرج بنفسك

توقّع الناتج، ثم اتبع الخطوات أدناه باستخدام أزرار المتتبّع.

public class CallStack {
    static int square(int x) {
        int result = x * x;
        return result;
    }

    static int sumOfSquares(int a, int b) {
        int first = square(a);
        int second = square(b);
        return first + second;
    }

    public static void main(String[] args) {
        int answer = sumOfSquares(3, 4);
        System.out.println(answer);
    }
}
الناتج
25
  1. اضغط «تتبّع سطرًا سطرًا»يتوقف عند أول سطر في main، وفي المكدس إطار واحد: main().
  2. اضغط «دخول» (F7)يظهر الإطار sumOfSquares() فوق main()، وفيه الصندوقان a = 3 وb = 4.
  3. اضغط «دخول» مرة أخرىيظهر الإطار square() في الأعلى وفيه x = 3. الآن في المكدس ثلاثة إطارات.
  4. اضغط «خروج من الدالة» (Shift+F8)يختفي الإطار square() وصناديقه، ويظهر first = 9 في sumOfSquares().
  5. اضغط «السطر التالي» (F8)يُنفَّذ الاستدعاء الثاني كاملًا دون الدخول إليه، ويظهر second = 16.
  6. اضغط «خروج من الدالة» ثم «متابعة» (F9)تعود إلى main ومعها answer = 25، ثم يكمل البرنامج حتى النهاية.

توقف المتتبّع عند السطر int result = x * x; في البرنامج أعلاه. ما الإطار الذي في أعلى المكدس؟

تتبّع التنفيذ بإصبعك من main. ماذا يطبع؟

public class FlowOrder {
    static void middle() {
        System.out.println("B");
    }

    public static void main(String[] args) {
        System.out.println("A");
        middle();
        System.out.println("C");
        middle();
    }
}
أظهر الناتج
الناتج
A
B
C
B

لماذا؟ بعد انتهاء كل استدعاء يعود التنفيذ إلى السطر الذي يلي الاستدعاء في main، فتُطبع B مرتين، مرة لكل استدعاء.

الدالة التي تعد بقيمة يجب أن تُرجعها في كل مسار

مسار بلا return

ماذا تُرجع الدالة إذا كان a أصغر من b أو يساويه؟ أكمل الدالة لتعمل مع كل الحالات.

public class MissingReturn {
    static int max(int a, int b) {
        if (a > b) {
            return a;
        }
    }

    public static void main(String[] args) {
        System.out.println(max(2, 8));
    }
}
رسالة المترجمmissing return statement
أظهر التصحيح
public class MissingReturn {
    static int max(int a, int b) {
        if (a > b) {
            return a;
        }
        return b;
    }

    public static void main(String[] args) {
        System.out.println(max(2, 8));
    }
}
الناتج
8

لماذا؟ يتأكد المترجم أن كل طريق داخل الدالة ينتهي بقيمة. وإذا كان الشرط خطأ هنا تصل الدالة إلى نهايتها دون قيمة. لاحظ أن الرسالة تشير إلى } الأخيرة في الدالة، لأن المشكلة هي وصول التنفيذ إليها.

هل تُترجم هذه الدالة؟

static int larger(int a, int b) {
    if (a >= b) {
        return a;
    }
    if (a < b) {
        return b;
    }
}

الاستدعاء يجب أن يطابق التعريف في الاسم والعدد والنوع

عدد الوسائط خطأ

الدالة تحتاج إلى وسيطين، ونحن أعطيناها واحدًا. أضف الارتفاع 4.

public class WrongCount {
    static int area(int width, int height) {
        return width * height;
    }

    public static void main(String[] args) {
        System.out.println(area(3));
    }
}
رسالة المترجمcannot be applied to given types
أظهر التصحيح
public class WrongCount {
    static int area(int width, int height) {
        return width * height;
    }

    public static void main(String[] args) {
        System.out.println(area(3, 4));
    }
}
الناتج
12

لماذا؟ يكمل المترجم الرسالة بسطرين: required وهو ما تطلبه الدالة، وfound وهو ما أعطيته. قارن بينهما لتعرف ما ينقص.

نوع الوسيط خطأ

علامتا التنصيص جعلتا الوسيط نصًا. أصلح الاستدعاء.

public class WrongType {
    static int twice(int n) {
        return n * 2;
    }

    public static void main(String[] args) {
        System.out.println(twice("21"));
    }
}
رسالة المترجمincompatible types: String cannot be converted to int
أظهر التصحيح
public class WrongType {
    static int twice(int n) {
        return n * 2;
    }

    public static void main(String[] args) {
        System.out.println(twice(21));
    }
}
الناتج
42

لماذا؟ إسناد الوسيط إلى المعامل يشبه الإسناد العادي: الصندوق int n لا يقبل نصًا. لذلك تشبه الرسالة ما رأيناه في int age = "19";.

دالة غير معرّفة

حرف واحد يفرق بين الاسمين. أصلح الاستدعاء.

public class Undefined {
    static void printLine() {
        System.out.println("-----");
    }

    public static void main(String[] args) {
        printline();
    }
}
رسالة المترجمcannot find symbol
أظهر التصحيح
public class Undefined {
    static void printLine() {
        System.out.println("-----");
    }

    public static void main(String[] args) {
        printLine();
    }
}
الناتج
-----

لماذا؟ Java تميز بين الحروف الكبيرة والصغيرة، فالاسم printline ليس printLine. وهي الرسالة نفسها التي تظهر مع متغير غير معرّف، والسطر symbol: فيها يدلك على الاسم الذي لم يجده المترجم.

أسئلة المراجعة

ماذا تعني void في تعريف الدالة؟

في ملف كتبنا فيه خمس دوال قبل main، من أين يبدأ التشغيل؟

تتبّع على الورق، ثم تأكد باستخدام «تتبّع سطرًا سطرًا».

public class ReviewTrace {
    static int addOne(int n) {
        return n + 1;
    }

    static void show(int n) {
        System.out.println("n = " + n);
    }

    public static void main(String[] args) {
        int value = addOne(4);
        show(value);
        show(addOne(value) * 2);
    }
}
أظهر الناتج
الناتج
n = 5
n = 12

لماذا؟ value تساوي 5. ثم addOne(5) تعطي 6، وتُضرب في 2 فتكون 12 قبل أن تصبح وسيطًا لـ show.