جافا:دوري عامة نوع العلاقة لا تسمح المدلى بها من supertype (javac علة)

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

  •  03-07-2019
  •  | 
  •  

سؤال

واجهت تماما سلوك غريب من مترجم جافا.
أنا لا يمكن أن يلقي supertype إلى نوع فرعي عندما دوري نوع عام العلاقة تشارك.

JUnit حالة اختبار إعادة إنشاء المشكلة:

public class _SupertypeGenericTest {

    interface ISpace<S extends ISpace<S, A>, A extends IAtom<S, A>> {
    }

    interface IAtom<S extends ISpace<S, A>, A extends IAtom<S, A>> {
    }

    static class Space
            implements ISpace<Space, Atom> {
    }

    static class Atom
            implements IAtom<Space, Atom> {
    }

    public void test() {
        ISpace<?, ?> spaceSupertype = new Space();
        IAtom<?, ?> atomSupertype = new Atom();

        Space space = (Space) spaceSupertype;  // cast error
        Atom atom = (Atom) atomSupertype;  // cast error
    }
}

مترجم الخطأ الناتج:

_SupertypeGenericTest.java:33: inconvertible types
found   : pinetag.data._SupertypeGenericTest.ISpace<capture#341 of ?,capture#820 of ?>
required: pinetag.data._SupertypeGenericTest.Space
                Space space = (Space) spaceSupertype;
                                    ^

_SupertypeGenericTest.java:34: inconvertible types
found   : pinetag.data._SupertypeGenericTest.IAtom<capture#94 of ?,capture#48 of ?>
required: pinetag.data._SupertypeGenericTest.Atom
                Atom atom = (Atom) atomSupertype;
                                ^
2 errors

ملاحظة:أنا باستخدام Netbeans أحدث الجذع المجمعة النمل, أحدث جافا 6 الإفراج.
حاولت استخدام النمل من سطر الأوامر (Netbeans يولد build.xml ملف) ولكن النتائج في نفس الأخطاء.

ما هو الخطأ ؟
هل هناك طريقة أنيقة حل هذه المشكلة ؟

الشيء الغريب هو:Netbeans لا علامة أخطاء (وليس حتى تحذيرات) في رمز معين.

تحرير:
لا, الآن أفهم لا شيء!
الكسوف 3.4.1 لا مارك ولا تحذيرات أو أخطاء ، برمجيا رمز دون عناء!!!
كيف يمكن أن يكون هذا ؟ فكرت باستخدام النمل من سطر الأوامر جنبا إلى جنب مع build.xml التي تقدمها Netbeans' أن تكون محايدة.
أنا في عداد المفقودين شيئا ؟

تحرير 2:
باستخدام JDK7 مكتبة JDK7 شكل رمز, netbeans برمجيا دون الأخطاء تحذيرات!
(أنا باستخدام 1.7.0-ea-b55)

تحرير 3:
تم تغيير العنوان تشير إلى أن نتعامل مع javac علة.

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

المحلول

أنا لا أدعي أن نفهم بسهولة المعقدة هذه الأنواع العامة ، ولكن إذا كان يمكنك العثور على بعض التعليمات البرمجية التي تجمع في javac و لا في ecj (الكسوف مترجم) ، ثم ملف تقرير الشوائب مع كل الشمس و الكسوف ووصف حالات كليري (أفضل إذا كنت أذكر أيضا أنك قدمت كل التقارير الشوائب ذكر كل منهما عناوين url ، على الرغم من أن الشمس قد يستغرق بعض الوقت قبل أن الخلل هو متاح للجمهور).

لقد فعلت ذلك في الماضي و حصلت على جيد حقا حيث الردود

  1. واحدة من الفرق أحسب ما النهج الصحيح هو (إعطاء ترجمة خطأ أو تحذير أو لا شيء)
  2. و خلل مترجم ثابت

لأن كلا المجمعين تنفيذ نفس المواصفات, واحد منهم هو تعريف خاطئ ، إلا إذا كان واحد منهم يجمع رمز.

للعلم:

حاولت ترجمة نموذج التعليمات البرمجية مع javac (javac 1.6.0_13) ، ecj (Eclipse مترجم جافا 0.894_R34x, 3.4.2 الإصدار) ، javac اشتكى بصوت عال و لم يسفر عن أي .class ملفات, في حين ecj فقط اشتكى بعض المتغيرات غير المستخدمة (تحذيرات) وتنتج جميع المتوقعة .class ملفات.

نصائح أخرى

لقد انتهت عدم استخدام الأدوية من أجل هذا:

    @Test
    public void test() {
            ISpace spaceSupertype = new Space();
            IAtom atomSupertype = new Atom();

            Space space = (Space) spaceSupertype;  // ok
            Atom atom = (Atom) atomSupertype;  // ok
    }

ماذا يحمل لك مرة أخرى من استخدام أنواع دون البدل?

public void test() {
    ISpace<Space, Atom> spaceSupertype = new Space();
    IAtom<Space, Atom> atomSupertype = new Atom();

    Space space = (Space) spaceSupertype;  // no error
    Atom atom = (Atom) atomSupertype;  // no error
}

هكذا يقرأ أكثر وضوحا ، بالإضافة إلى أنه يجمع يعمل :) وأعتقد أن هذا سيكون "وسيلة أنيقة حل المشكلة"

قد تكون المشكلة أنك تحاول أن يلقي IAtom<?, ?> إلى Atom (وهو Atom<Atom, Space>).كيف هيك هو نظام من المفترض أن تعرف أن ? قد تكون الذرة و الفضاء أو لا ؟

عندما كنت لا تعرف أنواع عصا في مكان الأدوية تمتلئ ، وعادة ما تترك من شيء كامل ، كما في

ISpace spaceSupertype = new Space();

أن يولد مترجم تحذير (لا خطأ) لكن التعليمات البرمجية الخاصة بك سوف لا تزال تنفيذ (وإن كان النوع الفعلي لا يلقي متوافق, سوف تحصل على خطأ وقت التشغيل).

هذا كله لا معنى أنظر ، على الرغم من.أنت تقول أنك تحتاج الكتابة قوية, ثم كنت عصا ? حيث أنواع الذهاب.ثم يستدير و حاول أن يلقي لهم.

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

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

اسأل نفسك: "هل أنا حقا بحاجة قوية أنواع ؟ ما لا كسب لي؟" فإنه من الأفضل عدم إضافة حقول منذ كنت تستخدم واجهات.(نضع في اعتبارنا أنه إذا الحقول الوصول إليها فقط من خلال طرق ، ثم أنت فقط إضافة طرق إلى الواجهة العمومية.) إذا كان يضيف الطرق ، ثم باستخدام واجهات واحد IAtom و ISpace هنا هو فكرة سيئة لأنك سوف تكون قادرة على استخدام test() مع هذا النوع على أي حال. test() لن التعميم إلى تطبيقات أخرى ISpace/IAtom.إذا كانت جميع التطبيقات سوف تكون في وضع هنا لديهم نفس الأساليب تحتاج test() ولكن ليس كل تطبيقات IAtom/ISpace يكون لهم ، تحتاج وسيطة subinterface:

public interface IAtom2 extends IAtom
{
    [additional methods]
}

ثم يمكنك استخدام IAtom2 بدلا من IAtom في test().ثم كنت قد تلقائيا حصلت على الكتابة تحتاج ولا تحتاج إلى الأدوية.تذكر ، إذا مجموعة من الطبقات المشترك واجهة العام (مجموعة من الطرق و الحقول) هذا العام واجهة هو مرشح جيد supertype أو واجهة لها.أنا تصف ما هو شيء مثل متوازي الاضلاع, مستطيل, مربع علاقة حيث كنت في محاولة تخطي المستطيل جزء.

إذا كنت لا تنوي تصميم, فكرة أخرى هي أن تسقط دوري الأدوية و فقط لا مثيل الاختبار عن طريق instanceof:

if (spaceSupertype instanceof Space)
{
    Space space = (Space)spaceSupertype;
    ...
}
else
...
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top