كما نعلم، لغة جافا هي لغة برمجة كائنية التوجه. وبعبارة أخرى، فإن المفهوم الأساسي، أي أساس الأساس، هو أن كل شيء هو كائن. يتم وصف الكائنات باستخدام الفئات. الطبقات، بدورها، تحدد الحالة والسلوك. على سبيل المثال، قد يكون للحساب البنكي حالة على شكل مبلغ من المال في الحساب وله سلوكيات تزيد وتنقص رصيد الحساب. في جافا، يتم تنفيذ السلوكيات من خلال الأساليب. تعلم كيفية تحديد الأساليب يأتي في بداية دراساتك في Java. على سبيل المثال، في البرنامج التعليمي الرسمي لـ Oracle، تحت عنوان " Defining Methods
". هناك أمران مهمان يجب مراعاتهما هنا:
- كل طريقة لها توقيع. يتكون التوقيع من اسم الطريقة ومعلمات الإدخال الخاصة بها.
- يجب تحديد نوع الإرجاع للطرق. أنت تعلن عن نوع الإرجاع الخاص بالطريقة في إعلان الطريقة الخاص بها.
ماذا تفعل العودة في جافا
الكلمة الأساسية return عبارة عن بيان تحكم في التدفق، كما هو موضح في برنامج Oracle التعليمي هنا . يمكنك أيضًا القراءة عن كيفية إرجاع القيم في قسم " إرجاع قيمة من طريقة " في البرنامج التعليمي الرسمي. يتتبع المترجم بعناية ما إذا كان يمكنه التأكد من أن قيمة الإرجاع الخاصة بالطريقة تتطابق مع نوع الإرجاع المحدد للطريقة. دعونا نستخدم IDE عبر الإنترنت الخاص بـ Tutorialspoint للنظر في مثال. دعونا نلقي نظرة على المثال البدائي:public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello World");
}
}
كما نرى، يتم هنا تنفيذ الطريقة الرئيسية ، وهي نقطة الدخول للبرنامج. يتم تنفيذ أسطر التعليمات البرمجية من الأعلى إلى الأسفل. لا يمكن لطريقتنا الرئيسية إرجاع قيمة. إذا حاولنا إرجاع قيمة هناك، فسوف نحصل على خطأ: "خطأ: يجب أن تقوم الطريقة الرئيسية بإرجاع قيمة من النوع void" . وفقا لذلك، يتم إخراج الطريقة ببساطة إلى الشاشة. الآن دعنا ننقل السلسلة الحرفية إلى طريقة منفصلة لإنشاء الرسالة:
public class HelloWorld {
public static void main(String[] args) {
System.out.println(getHelloMessage());
}
public static String getHelloMessage() {
return "Hello World";
}
}
كما نرى، استخدمنا الكلمة الأساسية return للإشارة إلى القيمة المرجعة، والتي مررناها بعد ذلك إلى طريقة println . يشير تعريف طريقة getHelloMessage إلى أن الطريقة ستُرجع سلسلة . يسمح هذا للمترجم بالتحقق من أن إجراءات الطريقة متوافقة مع كيفية إعلانها. وبطبيعة الحال، يمكن أن يكون نوع الإرجاع المحدد في إعلان الطريقة أوسع من نوع القيمة التي تم إرجاعها بالفعل في الكود، أي الشيء المهم هو أن تحويل النوع ممكن. وإلا، فسنحصل على خطأ في وقت الترجمة: "خطأ: أنواع غير متوافقة" . بالمناسبة، ربما يكون لديك سؤال: لماذا يعتبر الإرجاع بمثابة بيان تدفق التحكم؟ لأنه يمكن أن يعطل التدفق الطبيعي من أعلى إلى أسفل للبرنامج. مثال:
public class HelloWorld {
public static void main(String[] args) {
if (args.length == 0) {
return;
}
for (String arg : args) {
System.out.println(arg);
}
}
}
كما ترون من المثال، فإننا نقوم بمقاطعة الطريقة الرئيسية في برنامج Java إذا تم استدعاؤها بدون وسائط. من المهم أن تتذكر أنه إذا كان لديك رمز بعد بيان الإرجاع ، فلن يكون من الممكن الوصول إليه. سوف يلاحظ ذلك مترجمنا الذكي ويمنعك من تشغيل مثل هذا البرنامج. على سبيل المثال، لا يتم ترجمة هذا الرمز:
public static void main(String[] args) {
System.out.println("1");
return;
// we use output method after return statement, which is incorrect
System.out.println("2");
}
هناك اختراق قذر واحد للتغلب على هذا. على سبيل المثال، لأغراض التصحيح، أو لسبب آخر. يمكن إصلاح الكود أعلاه عن طريق تغليف عبارة الإرجاع في كتلة if :
if (2==2) {
return;
}
بيان الإرجاع أثناء معالجة الأخطاء
هناك شيء آخر صعب للغاية، وهو أنه يمكننا استخدام return مع معالجة الأخطاء. أريد أن أقول على الفور أن استخدام عبارة الإرجاع في كتلة الالتقاط يعد أمرًا سيئًا للغاية، لذا يجب عليك تجنبه. لكننا بحاجة إلى مثال، أليس كذلك؟ ها هو:public class HelloWorld {
public static void main(String[] args) {
System.out.println("Value: " + getIntValue());
}
public static int getIntValue() {
int value = 1;
try {
System.out.println("Something terrible happens");
throw new Exception();
} catch (Exception e) {
System.out.println("Cached value: " + value);
return value;
} finally {
value++;
System.out.println("New value: " + value);
}
}
}
للوهلة الأولى، يبدو أنه يجب إرجاع 2، حيث يتم تنفيذه دائمًا . لكن لا، القيمة المرجعة ستكون 1، وسيتم تجاهل التغيير الذي تم إجراؤه على المتغير في الكتلة الأخيرة . علاوة على ذلك، لنفترض أن هذه القيمة تحتوي على كائن ونقول value = null في الكتلة الأخيرة . ثم سيتم إرجاع هذا الكائن، وليس فارغًا، في كتلة الالتقاط . لكن عبارة الإرجاع ستعمل بشكل صحيح في الكتلة الأخيرة . من الواضح أن زملائك في العمل لن يشكروك على المفاجآت الصغيرة التي تتضمن بيانات الإرجاع.
void.class
وأخيرا. هناك هذا البناء الغريب الذي يمكنك كتابته: void.class . همم. لماذا وماذا يعني؟ هناك بالفعل العديد من الأطر والحالات الصعبة التي تتضمن Java Reflection API حيث يمكن أن يكون ذلك مفيدًا جدًا. على سبيل المثال، يمكنك التحقق من النوع الذي تُرجعه الطريقة:import java.lang.reflect.Method;
public class HelloWorld {
public void getVoidValue() {
}
public static void main(String[] args) {
for (Method method : HelloWorld.class.getDeclaredMethods()) {
System.out.println(method.getReturnType() == void.class);
}
}
}
يمكن أن يكون هذا مفيدًا في أطر الاختبار حيث تحتاج إلى استبدال الكود الفعلي في الأساليب. لكن للقيام بذلك، عليك أن تفهم كيف تتصرف الطريقة (أي النوع الذي تُرجعه). هناك أيضًا طريقة ثانية لتنفيذ الطريقة الرئيسية في الكود أعلاه:
public static void main(String[] args) {
for (Method method : HelloWorld.class.getDeclaredMethods()) {
System.out.println(method.getReturnType() == Void.TYPE);
}
}
يمكنك قراءة مناقشة مثيرة للاهتمام حول الفرق بين الاثنين في Stack Overflow: ما الفرق بين java.lang.Void وvoid؟
GO TO FULL VERSION