模板方法的返回类型与返回的实例不匹配
我在接口中的一个静态模板方法上遇到了问题。这个接口没有什么特殊之处,但方法声明有点棘手。代码看起来像这样:
public interface ItemSelectPanelFactory
{
public static final int MAX_RADIO_COUNT = 4;
@SafeVarargs
public static <T, V extends JPanel & LabeledInput<T>>
V createPanel(String label, T... items)
{
V result = null;
if (MAX_RADIO_COUNT < items.length)
{
result = new ItemSelectComboPanel<T>(label, items);
}
else
{
result = new ItemSelectRadioPanel<T>(label, items);
}
return result;
}
}
// one of those classes is declared as:
public class ItemSelectRadioPanel<T> extends JPanel
implements ActionListener, LabeledInput<T>
{...}
// The other looks like
public class ItemSelectComboPanel<T>
extends AbstractLabeledInputComponent<T, JComboBox<T>>
{...}
// but that inheritance chain does also derive from JPanel.
// the other interface declaration is:
public interface LabeledInput<T>
{
public T getValue();
}
除了ItemSelectPanelFactory类之外,其他一切都能编译通过。我的编译器调用看起来是:
javac -d obj -Xlint:unchecked -classpath obj -sourcepath . . .
编译器只报告以下两个错误:
src/flb/gui/ItemSelectPanelFactory.java:61: error: incompatible types: ItemSelectComboPanel<T> cannot be converted to V
result = new ItemSelectComboPanel<T>(label, items);
^
where T,V are type-variables:
T extends Object declared in method <T,V>createPanel(String,T...)
V extends JPanel,LabeledInput<T> declared in method <T,V>createPanel(String,T...)
src/flb/gui/ItemSelectPanelFactory.java:65: error: incompatible types: ItemSelectRadioPanel<T> cannot be converted to V
result = new ItemSelectRadioPanel<T>(label, items);
^
where T,V are type-variables:
T extends Object declared in method <T,V>createPanel(String,T...)
V extends JPanel,LabeledInput<T> declared in method <T,V>createPanel(String,T...)
这些行号确实与方法中的 "result=" 语句相匹配。我能看出,编译器有可能不会展开继承链,针对不是JPanel直接子类的那个类的情况,但不会出现在直接的那一个上。我猜这与我对模板类型V 的定义有关,但我看不出到底出了什么问题。
解决方案
确实需要进行强制类型转换,因为你已将结果声明为那样。
你定义的方法签名表示调用者(而不是 createPanel 的主体)有权决定 V 是什么,且函数必须向它返回那种V,无论其他情况如何。这并不是你当前的实现,因此这个强制转换不安全。
事实上,在Java的类型系统中,没有一种方式可以让函数的结果类型是“同时扩展自JPanel和 LabeledInput的某种类型”。
最可行的替代方案是定义你自己的一个抽象类,该类同时扩展JPanel和 LabeledInput,然后让ItemSelectComboPanel和 ItemSelectRadioPanel都继承该类。
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。