为什么ChangeListener的getSource()没有返回用于生成事件的预制对象?

时间:2013-07-25 00:00:13

标签: java swing changelistener

为什么我不能将ChangeEvent对象强制转换为JSpinner对象以便我可以访问getValue()方法,为什么e.getSource()只返回用于生成的类型的预转对象事件? e.getSource()的第一个用法清楚地表明它知道正在使用JSpinner,那么为什么不把它重新抛出呢?看起来它更简单。我假设有安全理由不这样做,但我想看到或听到一个具体的例子,为什么这将是一个坏的东西作为默认用法。

不安全吗?这只是糟糕的建筑吗?

public class SpinnerPanel extends JPanel implements ChangeListener {

...

SpinnerPanel()
{
    birthdaySpinner.addChangeListener(this);
    add(birthdaySpinner);
}

@Override
public void stateChanged(ChangeEvent e) 
{
    System.out.println(e.getSource());

    JSpinner spinner = (JSpinner)e.getSource();
    System.out.println(spinner.getValue());
}
}

1 个答案:

答案 0 :(得分:2)

源是JSpinner的事实在运行时已知。您在编译时中使用泛型可以实现您所描述的那种“自动类型转换”,但当时并不知道侦听器可能会在哪里结束。例如,您可以获取您的微调器,获取所有侦听器的列表,然后将这些侦听器添加到另一个窗口小部件,如复选框。代码中没有任何内容可以在编译时告诉编译器这种情况不会发生,所以没有什么可以告诉编译器源代码总是一个微调器。

从理论上来说可以以某种方式使用泛型。对于源自类ChangeEvent<T>的组件的更改,您可以T。您可以使用方法ChangeListener<T> stateChanged(ChangeEvent<? extends T>)。但那么类T的给定组件的所有侦听器的类型是什么?如果是List<ChangeEvent<T>>,那么您将无法在该列表中添加通用ChangeListener<Object>。所以它必须是List<ChangeEvent<? super T>>。但是如果你在任何组件中都有这样的列表,那么它对于所有派生组件都是相同的类型,而不是像泛型方法所建议的更具体的类型。

所以总的来说,我认为这种泛型方法会使代码编写和维护更加困难,可能会在某些地方留下漏洞,在向后兼容性方面可能会很糟糕,总的来说不值得努力。