我使用Java泛型实现了一个简单的付款处理系统。它可以在运行时进行编译和运行,但是我对“未经检查的转换”警告感到困惑。
enum PaymentType {
CARD, SAVED_CARD
}
interface PayData {
}
class CardPayData implements PayData {
private String cardNumber;
private String cvc;
}
class SavedCardPayData implements PayData {
private String cardId;
}
interface PayService<T extends PayData> {
void pay(T payData);
}
class CardPayService implements PayService<CardPayData> {
@Override
public void pay(CardPayData cardPayData) {
// i need concrete class CardPayData here
}
}
class SavedCardPayService implements PayService<SavedCardPayData> {
@Override
public void pay(SavedCardPayData payData) {
// i need concrete class SavedCardPayData here
}
}
class PayServiceFactory {
private CardPayService cardPayService = new CardPayService();
private SavedCardPayService savedCardPayService = new SavedCardPayService();
public PayService getService(PaymentType paymentType) {
if (paymentType.equals(PaymentType.CARD))
return cardPayService;
else
return savedCardPayService;
}
}
class PaymentProcessor {
PayServiceFactory payServiceFactory = new PayServiceFactory();
public void serveRequest(PayData payData, PaymentType paymentType) {
// here i have 'unchecked cast' warning
PayService<PayData> payService = (PayService<PayData>) payServiceFactory.getService(paymentType);
payService.pay(payData);
}
}
试图摆脱这种警告的任何尝试都会导致我出现编译错误。例如,我尝试从我的工厂方法返回泛型类型,但只收到编译错误:
// return generic
public PayService<? extends PayData> getService(PaymentType paymentType) { ... }
public void serveRequest(PayData payData, PaymentType paymentType) {
PayService<? extends PayData> payService = payServiceFactory.getService(paymentType);
// error here:
// pay (capture <? extends PayData>) in PayService cannot be applied to (PayData)
payService.pay(payData);
}
最佳答案
类的设计本质上是不安全的类型。具体来说,serveRequest
方法:
public void serveRequest(PayData payData, PaymentType paymentType) {
PayService<PayData> payService = (PayService<PayData>) payServiceFactory.getService(paymentType);
payService.pay(payData);
}
无法强制
payData
的运行时类型与payService.pay
期望的兼容。根据paymentType
,getService
可能在运行时返回PayService<Anything>
,因此payService.pay
可能会在运行时期望任何类型。因为payData
应该是的类型只能在运行时知道,所以不能在编译时强制执行。最好的办法是放入
SuppressWarnings
并使payData
通用:@SuppressWarnings("unchecked")
public <T extends PayData> void serveRequest(T payData, PaymentType paymentType) {
PayService<T> payService = (PayService<T>) payServiceFactory.getService(paymentType);
payService.pay(payData);
}