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