مترجم جافا غرائب:ميدانيا أعلن في نفس الفئة ، ولكن "غير مرئية"

StackOverflow https://stackoverflow.com/questions/1604147

سؤال

الكسوف مترجم يرفض ترجمة التعليمات البرمجية التالية ، مشيرا إلى أن الميدان 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;
    }
}

أعتقد أن alphazero هو الصحيح هنا, هذا الكسوف هو أكثر حذرا.

غريب جدا.لسبب غير معروف (بالنسبة لي) ، eclipse مترجم يتطلب صريح المدلى بها:

void foo(Object o) {
    String os = ((Test)getClass().cast(o)).s;
}

في حين أن رمز تماما برمجيا دون المدلى بها مع الشمس JDK (أنا تشغيل الإصدار 1.6.0_16 على جنو/لينكس).

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