الأدوية الجيرية: يبدو أن برنامج التحويل البرمجي غير قادر على إدراك أن النوع الذي تم تمريره إلى وسيطة هو نفسه الذي تم إرجاعه - لماذا؟

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

  •  30-09-2019
  •  | 
  •  

سؤال

دعنا نقول أن لدي العديد من pojos التي تمد جميعها supertype المشتركة ، BaseObject.

انا املك GenericDao الذي يُعلن باسم public interface GenericDao<T>.

لكل DAO خاص بالأنواع ، لدي واجهة تمتد النوع العام وتقييده على نوع خرساني (public interface UserDao extends GenericDao<User>) ثم تنفيذ DAO نوع محدد.

في فصل يحاول استخدام عدد من GenericDao التطبيقات ، لدي طريقة تبدو

public <T extends BaseObject> long create(T object) {
    return getDao(object.getClass()).save(object);
}

إذا قمت بتنفيذ getDao() بحيث تكون المعلمة Class كائن ، مثل

private <T extends BaseObject> GenericDao<T> getDao(Class<T> clazz) { ... }

ثم الدعوة إلى getDao(object.getClass() في ال create() تفشل الطريقة في التجميع - يبدو أن المترجم يفسر نوع الإرجاع getDao() كما

GenericDao<? extends BaseContractObject>

بدلا من الاعتراف بذلك getDao(Class<T>) سوف يعيدني أ GenericDao من نفس النوع T.

هل يمكن لأحد أن يشرح لماذا هذا؟ أفهم أن المظاهر المتكررة لنفس النوع المرتبط أو البطاقة البرية لا تشير إلى نفس النوع ؛ ومع ذلك يبدو أن المترجم يجب أن يتعرف عليه من توقيع getDao(Class<T>) يجب أن تكون T قد تم إقرارها هي نفسها (ولكن من الواضح أنها غير قادر على الاعتراف بذلك ، لماذا هو الجزء الذي فشل في الفهم).

إذا حددت بدلاً من ذلك getDaoتوقيع ليكون

private <T extends BaseContractObject> GenericDao<T> getDao(T obj) { ... }

ثم لا توجد مشكلة في تجميع أ create() التنفيذ الذي يبدو

public <T extends BaseContractObject> long create(T object) {
    return getDao(object).save(object);
}

فلماذا يكون المترجم قادرًا على الاعتراف في هذه الحالة بأن T تم تمرير الحجة إلى getDao(T) هو نفسه T في نوع العودة ، في حين أنه لم يستطع التعرف على هذا عندما كانت الوسيطة Class<T>?

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

المحلول

التعبير object.getClass(), ، حيث يكون الكائن من النوع T extends BaseObject, ، يعود أ Class<? extends BaseObject>, ، ليس أ Class<T> كما قد يتوقع المرء. لذا، getDao() يعيد داو من نفس النوع الذي يتلقاه ؛ إنه فقط لا يتلقى النوع المتوقع.

نصائح أخرى

هذه مشكلة في محو النوع الكلاسيكي. getClass() لديه التوقيع التالي:

public final native Class<? extends Object> getClass();

اذا كان لديك String وفعل getClass() على ذلك ، الفصل الذي تحصل عليه هو Class<? extends String>. قراءة Javadocs:

 * @return The <code>java.lang.Class</code> object that represents
 *         the runtime class of the object.  The result is of type
 *         {@code Class<? extends X>} where X is the
 *         erasure of the static type of the expression on which
 *         <code>getClass</code> is called.

ستحتاج إلى إجبار الممثلين التاليين على العمل:

@SuppressWarnings("unchecked")
Class<T> clazz = (Class<T>)object.getClass();
return getDao(clazz).save(object);

هذا يناسبني.

أعتقد أن هذا يجب أن يفسر لماذا لا يفعل القيد ما تتوقعه:

http://www.angelikalanger.com/genericsfaq/faqscesections/typeparameters.html#faq206

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