سؤال

وهذا مسموح به في جافا:

for(int i=0;i<5;i++){
  final int myFinalVariable = i;
}

والكلمة لسؤالي هو final. هل يجوز للقيام متغير النهائي الذي يتغير مع كل تشغيل للحلقة؟ وكنت أتساءل هذا لنهائي يقول أنه لا يمكنك تغيير قيمة المتغير (الدعوة myFinalVariable = i فقط)، ولكن انا إعادة تعريف متغير كله مع final int.

هل هم متغيرين مختلفة تماما فقط يحمل نفس الاسم - مع المتغير من تشغيل السابقة من الحلقة تتجه بالفعل إلى أسفل الطريق إلى جامع القمامة

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

المحلول

نعم، فإنه يسمح. الكلمة final يعني أنه لا يمكنك تغيير قيمة المتغير <م> ضمن نطاقه . على سبيل المثال حلقة الخاص بك، يمكنك التفكير في متغير الخروج من نطاق في أسفل الحلقة، ثم يعود إلى نطاق مع قيمة جديدة في الجزء العلوي من الحلقة. وتعيين لمتغير داخل حلقة لا تعمل.

نصائح أخرى

وأنت على حق، لكل التكرار في الحلقة، كنت تقوم بإنشاء متغير جديد. المتغيرات تفعل تشترك في نفس الاسم، ولكن لا بأس لأنهم ليسوا في نفس النطاق. المثال التالي سوف <م> لا العمل:

final int myFinalVariable = 0;
for(int i=0;i<5;i++){
  myFinalVariable = i;
}

والمتغير هو مجرد موقع على المكدس. محاولة لإبقاء المتغيرات الخاصة بك مع صغير كما هو نطاق ممكن، ومحاولة لجعلها النهائي. ومع ذلك نطاق ونهائي أشياء شفرة المصدر عادل ... من رمز جيل / VM جهة نظر أنهم لا يهم على الإطلاق.

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

وتأخذ التعليمات البرمجية التالية:

public class X
{
    public static void main(final String[] argv)
    {
        foo();
        bar();
    }

    private static void foo()
    {
        for(int i=0;i<5;i++)
        {
            final int myFinalVariable = i;
        }
    }

    private static void bar()
    {
        for(int i=0;i<5;i++)
        {
            int myFinalVariable = i;
        }
    }
}

والمترجم ينتج بايت كود متطابقة لكل طريقة:

public class X extends java.lang.Object{
public X();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return

public static void main(java.lang.String[]);
  Code:
   0:   invokestatic    #2; //Method foo:()V
   3:   invokestatic    #3; //Method bar:()V
   6:   return

private static void foo();
  Code:
   0:   iconst_0
   1:   istore_0
   2:   iload_0
   3:   iconst_5
   4:   if_icmpge       15
   7:   iload_0
   8:   istore_1
   9:   iinc    0, 1
   12:  goto    2
   15:  return

private static void bar();
  Code:
   0:   iconst_0
   1:   istore_0
   2:   iload_0
   3:   iconst_5
   4:   if_icmpge       15
   7:   iload_0
   8:   istore_1
   9:   iinc    0, 1
   12:  goto    2
   15:  return

}

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

private static void car()
{
    int myFinalVariable;

    for(int i=0;i<5;i++)
    {
        myFinalVariable = i;
    }
}

private static void car();
  Code:
   0:   iconst_0
   1:   istore_1
   2:   iload_1
   3:   iconst_5
   4:   if_icmpge       15
   7:   iload_1
   8:   istore_0
   9:   iinc    1, 1
   12:  goto    2
   15:  return

}

وكما أجاب: نعم، قد بمناسبة الواقع المتغيرات في حلقة باسم 'النهائي'. هنا هو تأثير ذلك (جافا 7، والكسوف نيلي، ماك OS X الأسد).

for ( int i = 0; i < 5; i++ ) {

  // With 'final' you cannot assign a new value.
  final int myFinalVariable = i;  // Gets 0, 1, 2, 3, or 4 on each iteration.
  myFinalVariable = 7; // Compiler error: The final local variable myFinalVariable cannot be assigned.

  // Without 'final' you can assign a new value.
  int myNotFinalVariable = i;  // Gets 0, 1, 2, 3, or 4 on each iteration.
  myNotFinalVariable = 7; // Compiler is OK with re-assignment of variable's value.

}

ومتغير أعلن داخل الحلقة لديهم نطاق فقط حتى إعدام واحدة من الحلقة.

وإعلان المتغير كما النهائي داخل الحلقة يجعل لا فرق للمتغير في الجانب الحلقة، ولكن إذا أردنا تعريف المتغير خارج الحلقة مع التعديل النهائي ثم القيمة التي تم تعيينها إلى نوع بدائي أو كائن تعيين لمتغير إشارة لا يمكن يمكن تغييرها.

في المثال أدناه لا توجد قضية مع الحلقات الأولى والثانية كل من الحلقات تعطي نفس الناتج، ولكن الحلقة الثالثة يعطي خطأ وقت الترجمة.

واختبار الطبقة العامة {

public static void main(String[] args) {
    for (int i = 0; i < 5; i++) {
        final int j= i;
        System.out.println(j);
    }
    for (int i = 0; i < 5; i++) {
        int j= i;
        System.out.println(j);
    }

    final int j;
    for (int i = 0; i < 5; i++) {
        j= i;
        System.out.println(j);
    }
}

و}

يرجى القيام تصحيح لي إذا كنت مخطئا.

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