java - ماذا تعني وسيطات نوع المنشئ عند وضعها*قبل*النوع؟




generics syntax (2)

استدعاء المنشئ العام

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

public class TypeWithGenericConstructor {

    public <T> TypeWithGenericConstructor(T arg) {
        // TODO Auto-generated constructor stub
    }

}

أفترض أنه في كثير من الأحيان عند إنشاء مثيل للصف خلال المنشئ العام ، لا نحتاج إلى جعل وسيطة الكتابة واضحة. فمثلا:

    new TypeWithGenericConstructor(LocalDate.now(ZoneId.systemDefault()));

الآن T هو LocalDate بوضوح. ومع ذلك ، قد تكون هناك حالات يتعذر فيها على Java استنتاج (استنتاج) وسيطة الكتابة. ثم نوفره بشكل صريح باستخدام بناء الجملة من سؤالك:

    new <LocalDate>TypeWithGenericConstructor(null);

بالطبع قد نوفره أيضًا على الرغم من أنه ليس ضروريًا إذا اعتقدنا أنه يساعد على القراءة أو لأي سبب:

    new <LocalDate>TypeWithGenericConstructor(LocalDate.now(ZoneId.systemDefault()));

في سؤالك يبدو أنك تتصل ببناء java.util.ArrayList . هذا المنشئ ليس عامًا (فقط فئة ArrayList ككل ، هذا شيء آخر). لماذا تسمح لك Java بتوفير وسيطات الكتابة في المكالمة عند عدم استخدامها ، راجع تعديلي أدناه. بلدي الكسوف يعطيني تحذير :

وسيطات الكتابة غير المستخدمة لمنشئ غير ArrayList () من النوع ArrayList؛ لا ينبغي أن يكون معلمات مع الحجج

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

فئة عامة مقابل منشئ عام

هل لوضع وسيطات الكتابة له نفس معنى وضعها بعد الكتابة؟ إذا لم يكن كذلك ، ماذا يعني تحديد المواقع المختلفة؟

لا ، الأمر مختلف. وسيطة النوع المعتادة / s بعد النوع ( ArrayList<Integer>() ) للفئة العامة . وسيطات النوع من قبل هي للمنشئ .

يمكن أيضًا دمج النموذجين:

    List<Integer> list = new <String, Long>ArrayList<Integer>();

سأعتبر هذا الأمر أكثر صوابًا نظرًا لأننا نرى الآن أن القائمة تقوم بتخزين كائنات Integer (ما زلت أفضل أن أتجاهل <String, Long> ، بالطبع).

لماذا يعد وجود وسيطات من النوعين قانونيًا عندما يكون لدى ArrayList 1 فقط؟

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

لماذا لا يسمح باستخدام وسيطات الكتابة التي لا معنى لها؟

تحرير بفضلSlaw للحصول على الرابط: يتيح Java وسيطات الكتابة على جميع استدعاءات الطريقة. إذا كانت الطريقة التي تم استدعاؤها عامة ، فسيتم استخدام وسيطات الكتابة ؛ إن لم يكن ، يتم تجاهلها. فمثلا:

    int length = "My string".<List>length();

نعم ، هذا سخيف. تقدم Java Language Specification (JLS) هذا التبرير في الفقرة الفرعية 15.12.2.1:

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

لا يتم الاحتفاظ بالوسيطة للبناة نظرًا لأنه لا يمكن تجاوزها مباشرة. لكنني أفترض أنهم يريدون أن يكون لديهم نفس القاعدة حتى لا تجعل القواعد المعقدة بالفعل معقدة للغاية. في أي حال ، يشير القسم 15.9.3 بشأن إنشاء مثيل new أكثر من مرة إلى 15.12.2.

الروابط

لقد واجهت مؤخرًا صيغة جافا هذه غير العادية (بالنسبة لي) ... إليك مثال على ذلك:

List list = new <String, Long>ArrayList();

لاحظ تحديد موضع وسيطات الكتابة <String, Long> ... ليس بعد الكتابة كالمعتاد ولكن من قبل. لا مانع من الاعتراف بأنني لم أرَ هذا النص من قبل. لاحظ أيضًا وجود وسيطات نوع 2 عندما يكون لدى ArrayList 1 فقط.

هل لوضع وسيطات الكتابة له نفس معنى وضعها بعد الكتابة؟ إذا لم يكن كذلك ، ماذا يعني تحديد المواقع المختلفة؟

لماذا يعد وجود وسيطات من ArrayList قانونيًا عندما يكون لدى ArrayList 1 فقط؟

لقد فتشت الأماكن المعتادة ، على سبيل المثال. Angelika Langer ، ولكن هنا لا يمكنك العثور على أي إشارة إلى بناء الجملة هذا في أي مكان بصرف النظر عن قواعد القواعد في ملف قواعد Java في مشروع ANTLR.


على ما يبدو ، يمكنك بادئة أي طريقة / مُنشئ غير عام بأي معلمة عامة تريدها:

new <Long>String();
Thread.currentThread().<Long>getName();

المترجم لا يهتم ، لأنه لا يجب أن يطابق أطروحات نوع الوسائط مع المعلمات العامة الفعلية.

بمجرد أن يقوم المترجم بالتحقق من الوسيطات ، فإنه يشكو من عدم تطابق:

Collections.<String, Long>singleton("A"); // does not compile

يبدو وكأنه خطأ مترجم بالنسبة لي.





generic-type-argument