سؤال

public class Main {

    static int x = Main.y;
//  static int x = y; //Not allowed; y is not defined
    static int y = x;
    public static void main(String[] args) {
        System.out.println(x);//prints 0
    }
}

كيف يُسمح لي باستخدام y الحوض ، ولكن ليس مباشرة؟

متى يتم تعريف y؟

هل كانت مفيدة؟

المحلول

يتم وصف القواعد الدقيقة التي تحكم الإشارة إلى الأمام إلى متغيرات الفصل في القسم §8.3.2.3 من JLS:

8.3.2.3 قيود على استخدام الحقول أثناء التهيئة

يحتاج إعلان العضو إلى الظهور بشكل نصي قبل استخدامه فقط إذا كان العضو مثيلًا (على التوالي static) حقل فئة أو واجهة C وجميع الشروط التالية عقد:

  • يحدث الاستخدام في حالة (على التوالي static) التهيئة المتغيرة لـ C أو في حالة (على التوالي static) مُهيئة C.
  • الاستخدام ليس على الجانب الأيسر من المهمة.
  • الاستخدام هو عبر اسم بسيط.
  • C هو فئة أو واجهة الأعمق التي تحيط الاستخدام.

يحدث خطأ في وقت الترجمة إذا لم يتم تلبية أي من المتطلبات الأربعة أعلاه.

هذا يعني أن خطأ وقت الترجمة من برنامج الاختبار:

  class Test {
      int i = j;  // compile-time error: incorrect forward reference
      int j = 1;
  }

في حين أن المثال التالي يجمع بدون خطأ:

  class Test {
      Test() { k = 2; }
      int j = 1;
      int i = j;
      int k;
  }

على الرغم من أن المنشئ (§8.8) للاختبار يشير إلى الحقل k الذي تم الإعلان عنه ثلاثة أسطر في وقت لاحق.

تم تصميم هذه القيود لالتقاط التهيئة الدائرية أو المشوهة في الترجمة أو المشوهة. وهكذا ، كلاهما:

class Z {
  static int i = j + 2; 
  static int j = 4;
}

و:

class Z {
  static { i = j + 2; }
  static int i, j;
  static { j = 4; }
}

يؤدي إلى أخطاء وقت الترجمة. لا يتم فحص الوصول بالطرق بهذه الطريقة ، لذلك:

class Z {
  static int peek() { return j; }
  static int i = peek();
  static int j = 1;
}
class Test {
  public static void main(String[] args) {
      System.out.println(Z.i);
  }
}

ينتج الإخراج:

0

نظرًا لأن التهيئة المتغيرة لـ I يستخدم طريقة الفئة نظرة خاطفة للوصول إلى قيمة المتغير J قبل تهيئة J بواسطة مُعمى متغير ، وفي هذه النقطة لا يزال لديه قيمته الافتراضية (§4.12.5).

نصائح أخرى

أفترض أنه من خلال استخدام الفصل ، فإن المترجم سيؤجل البحث عن المتغير حتى يكتمل الفصل ، لذلك يجد y ، ولكن إذا حددته مثل التعليق ، فهو لم يتم تعريفه بعد حتى يفشل

يتم تعريف المتغيرات الثابتة بترتيب الإعلان في الفصل ، أثناء تحميل الفصل. عندما تقوم JVM بتحميل Main صف دراسي، x سيتم تعريفها ، ثم y. لهذا السبب لا يمكنك استخدامه مباشرة y عند التهيئة x, ، يمكنك إنشاء شيء يسمى مرجع إلى الأمام, ، تشير إلى متغير غير محدد حاليًا ، وهذا غير قانوني للمترجم.

عند استخدام Main.y, ، أعتقد أن ما يلي يحدث:

  • أنت تحميل Main, x تسمى التهيئة
  • عندما تحدد x أن تكون متساوية ل Main.y, ، يرى المترجم إشارة إلى فئة ، لذلك سينتهي بالتعريف x إلى القيمة الحالية للعضو y الطبقة Main. يعامل هذه الحالة كما لو Main كان فئة مختلفة.

لاحظ أنه في هذه الحالة ، عند التهيئة x, y لم يتم تعريفه في الوقت الحالي. لذا x سيكون لها قيمة 0.

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

ربما يقوم المترجم بإنشاء مراجع المتغيرات الثابتة مع القيم الافتراضية مع الفئة في المكدس ، عند إنشاءه ثم يعين القيم المقدمة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top