我使用 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);
}
我是一名优秀的程序员,十分优秀!