مترجم جافا غرائب:ميدانيا أعلن في نفس الفئة ، ولكن "غير مرئية"
-
05-07-2019 - |
سؤال
الكسوف مترجم يرفض ترجمة التعليمات البرمجية التالية ، مشيرا إلى أن الميدان s غير مرئية.(IBM الجانب J مترجم أيضا يرفض ، مشيرا إلى أن "s لا يمكن حلها") لماذا ؟
public class Test {
String s;
void foo(Object o) {
String os = getClass().cast(o).s;
}
}
لغة جافا مواصفات الدول:
خلاف ذلك, نقول هناك الافتراضي التي يسمح فقط عندما الوصول تحدث من داخل الحزمة في أي نوع هو المعلنة.
طريقة فهمت الميدان المعلنة الوصول إليها في نفس تجميع الوحدة ، وبالتالي ضمن نفس الحزمة ، ولذلك ينبغي أن يكون الوصول إليها.
أكثر من الغريب ، إضافة مسبل من ? extends Test
إلى Test
يجعل المجال المرئي ، أيالتعليمة البرمجية التالية برمجيا:
public class Test {
String s;
void foo(Object o) {
Test t = getClass().cast(o);
String os = t.s;
}
}
أنا تعثرت عبر مترجم علة ، أو يساء فهمها جافا الأخص ؟
تحرير: أنا على كمبيوتر آخر الآن.هنا javac يقبل رمز ، ولكن الكسوف لا.الإصدارات على هذا الجهاز:
الكسوف منصة
الإصدار:3.4.2 Build id:M20090211-1700
JDK 1.6.0
تحرير 2 بل javac يقبل رمز.كان عندي اختبار عن طريق تشغيل النمل بناء ، والذي يستخدم IBM Ascpect J مترجم ...
المحلول
جرب هذا:
void foo(Object o) {
Test foo = getClass().cast(o);
String so = foo.s;
}
[تحرير لتوضيح]:
getClass().cast(o)
بإرجاع كائن من النوع 'capture#1-of? extends Test
'وليس Test
.وبالتالي فإن القضية تتعلق الأدوية وكيف مترجم يعامل.أنا لا أعرف تفاصيل المواصفات على الوراثة ولكن نظرا إلى أن بعض المجمعين (في التعليقات هنا) لا يقبل الكود ثم هذا هو إما ثغرة في المواصفات أو بعض هذه المجمعين ليست تماما حسب المواصفات.
[آخر خاطرة]:أعتقد الكسوف المترجم هو في الواقع (بعناية) الصحيح هنا.الكائن o
قد تكون في الواقع امتدادا اختبار (ومحددة في حزمة أخرى) و المترجم له أي وسيلة لمعرفة ما إذا كان هذا هو الحال أم لا.بحيث يتم التعامل معها بوصفها أسوأ الأحوال مثيل التمديد المحددة في حزمة أخرى.كان سوبر الصحيح إذا إضافة final
التصفيات المؤهلة إلى الدرجة Test
من شأنه أن يسمح الوصول إلى الميدان s
, لكنه لا.
نصائح أخرى
حسنا, دعونا نرى.أنا أقول المترجم لا يمكن بشكل صحيح يضمن foo()
سوف يتم استدعاؤها من قبل بعض الكيانات داخل الحزمة ، وبالتالي لا يمكن أن تضمن أن s
مرئيا.على سبيل المثال ، إضافة
protected void bar() {
foo();
}
ثم في بعض فرعية Banana
في آخر حزمة
public void quux() { bar(); }
و عفوا! getClass()
ينتج Banana
, التي لا يمكن أن نرى s
.
تحرير:بمعنى الأخرى.الحزمة.الموز لا لديك حقل s
.إذا الموز كانت في نفس الحزمة ، فإنه يمكن أن لا تزال لديها قناعاتها s
مكان الإقامة ، يجب أن أشير إلى Test
's s
عبر super
.
أنا لا يمكن إنتاج ما تقوله.هذه كل ترجمة على ما يرام بالنسبة لي دون تحذير أو خطأ أو أي شيء مع javac مباشرة.
ويندوز إكس بي ، javac 1.6.0_16
لا حاولت مع الكسوف (v3.4.1, Build id:M20080911-1700) و أول واحد يقول:
The field Test.s is not visible
على الأقل بالنسبة مترجم الامتثال مستوى 1.6 1.5.الشيء المضحك إن نظرتم إلى إصلاح سريع خيارات القوائم Change to 's'
القرار.والتي بالطبع لا يحل المشكلة.لذا الكسوف مترجم و الإصلاح السريع "مولد" يبدو أن لديهم وجهات نظر مختلفة في هذا أيضا؛ -)
على المترجم الالتزام مستوى 1.4 (كما كان متوقعا) في الكسوف في أول مرة أحصل على
s cannot be resolved or is not a field
وعلى الثاني واحدة أحصل على
Type mismatch: cannot convert from Object to Test
إن تحديد -source 1.4
و target -1.4
في سطر الأوامر مباشرة javac
يقول أول واحد
cannot find symbol
وعلى الثاني واحدة أحصل على
incompatible types
في الواقع في جميع الحالات تقريبا ، باستثناء عندما يكون ذلك مطلوبا من الأدوية ، إنه أفضل (وأكثر أمنا) إلى استخدام جافا يلقي المشغل.لقد ناقشت الأمر هنا.جافا يلقي المشغل لا تبدو أكثر مطول, لكنه الأداة المناسبة هنا.
استبدال cast
الطريقة مع المشغل يجمع ما يرام في الكسوف.
public class Test {
String s;
void foo(Object o) {
String os = ((Test) o).s;
}
}
غريب جدا.لسبب غير معروف (بالنسبة لي) ، eclipse مترجم يتطلب صريح المدلى بها:
void foo(Object o) {
String os = ((Test)getClass().cast(o)).s;
}
في حين أن رمز تماما برمجيا دون المدلى بها مع الشمس JDK (أنا تشغيل الإصدار 1.6.0_16 على جنو/لينكس).