المتغير النهائي الثابت العام في فئة جافا المستوردة
سؤال
لقد صادفت عبر رمز جافا في مكان عملي. إليك السيناريو: هناك 2 فصول - ClassA
و ClassB
.
ClassA
لا يوجد شيء ما عدا 4 قيم السلسلة الثابتة العامة في الداخل. والغرض منه هو استخدام هذه القيم مثل ClassA.variable
(لا تسألني لماذا، ليس رمزي).
ClassB
الواردات ClassA
. وبعد لقد حررت قيم السلسلة في ClassA
ورسمته. عندما هرب ClassB
أستطيع أن أرى أنه يستخدم القيم القديمة - ليست القيم الجديدة. اضطررت إلى إعادة ترجمة ClassB
لجعلها تستخدم قيم جديدة من ClassA
في (اضطررت إلى إعادة ترجمة الطبقات الأخرى التي تستورد ClassA
!)
هل هذا فقط بسبب jdk 1.6 أو يجب أن أعرف سابقا لإعادة ترجمة ClassB
أيضا! تنورني. :)
المحلول
إذا كانت قيم final
المتغيرات من الفصل ClassA
يحدث أن تكون ثوابت تجميع الوقت، قد يكون المترجم قد شمله في الفصول باستخدام ClassA
بدلا من إنشاء مرجع وقت التشغيل. أعتقد أن هذا ما حدث في حال وصفته.
مثال:
public class Flags {
public static final int FOO = 1;
public static final int BAR = 2;
}
public class Consumer {
public static void main(String[] args) {
System.out.println(Flags.FOO);
}
}
في هذا المثال، من المحتمل أن يتضمن المترجم قيمة FOO
في التعليمات العامة ولدت Consumer
بدلا من إنشاء مرجع وقت التشغيل المكافئ. إذا كانت قيمة FOO
التغييرات في وقت لاحق، سيكون عليك إعادة الترجمة Consumer
من أجل استخدام القيمة الجديدة.
هذه هي الأمثل، والتي لديها عدد قليل من المزايا فيما يتعلق بالكفاءة وسرعة البرنامج المترجمة. على سبيل المثال، قد تمكن القيمة الشريرة من التحسينات الإضافية في التعبيرات، والتي تستخدمها، على سبيل المثال:
int x = Flags.FOO * 10;
في هذا المثال، يتيح القيمة (هنا: 1) أن يلاحظ المحول البرمجي، أن الضرب لا فرق، ويمكن حذفه alltogether.
نصائح أخرى
إنها مشكلة التوافق الثنائية. يتم حل الإشارات إلى الحقول المستمرة في وقت الترجمة. السلوك الذي تراه هو الصحيح؛ إذا قمت بتغيير القيم في الفصل، فسيتعين عليك إعادة ترجمة العميل (فئة B). لتجنب مثل هذه المشاكل، فكر في إضافة ثوابت باستخدام نوع المعمنة، قدم في Java Release 5.0.
لماذا تحاول تجميع الفصول بشكل فردي؟
استخدم نظام الإنشاء مثل Maven أو Ant أو فقط دع IDE الخاص بك تفعل ذلك.
الشيء الآمن الوحيد الذي يجب القيام به هو إعادة ترجمة كل Java التي تعتمد على فئة Java التي تغيرت حتى يتم إعادة تجميع كل فئة يمكن إعادة تجميعها.
إذا كنت لا تستخدم القيم في رمز التبديل، فيمكنك القيام بذلك بدلا من ذلك:
public class A
{
public static final int FOO;
public static final String BAR;
static
{
FOO = 42;
BAR = "Hello, World!";
}
}
ثم لم يعد التحويل البرمجي رمز صلب القيم في الفئات الأخرى التي تستخدمها.
افترض أن الفئة تبدو وكأنها هذه:
public class ClassA {
public static final int FOO = 1;
public static final int BAR = 2;
}
إذا قمت بإعادة ترجمة ذلك، ستستمر ClassB في استخدام القيم القديمة. أعتقد أنه قد يعتمد على المحول البرمجي، لكنني أعتقد أن هذا هو السلوك النموذجي. إذا كنت لا ترغب في إعادة ترجمة Classb في كل مرة تتغير ثابتا في كلاسا، فسيتعين عليك فعل شيء مثل هذا:
public class ClassA {
public static final int FOO = CONST(1);
public static final int BAR = CONST(2);
public static int CONST(int i) { return i; }
}
Becuase الآن Javac غير راغب في ضم الثوابت. بدلا من ذلك، سيتصل بطريقة const (int) عند تشغيل التهيئة الثابتة في كلاسا.