在泛型中使用通配W和l承
本文是Sun官方以Blog形式发布的Java核心技术窍?JavaCoreTechTip)中的一?/a>Q它以非常简z的CZ展示了泛型通配W的使用Q初学Java泛型的朋友可以看看?2009.12.30最后更?
Java2q_Q标准版5.0(J2SE 5.0)为JavaE序设计语言及其q_引入了泛型。在最单的案例和典型的应用中,泛型能够识别集合容器中所存储的是否是你所期望的对象。所以,你可以特别说你有一个String或其它类型对象的ListQ而不是声UC的程序有一个Object的List。所以,如果你不心向该List中加入了错误cd的对象,~译器会告之你这个错误。该错误在~译时进行修复,而不用等Cq行该程序,且在E序q行到该处代码时Q在获取对象的操作中产生一个运行时的强制类型{换异常?br />
q就提出了泛型的W二个好处。P代器变得类型安全了。Iterator接口中的next()Ҏ会q回集合中下一个元素的cd安全版本?br />
但这q不是本文要介绍的泛型应用的H门Q那些窍门已?a >2005 Core Java Technologies Tip描述q了。在使用泛型Ӟ大多Ch都不能很好地理解对extends关键字的使用。一个典型的描述如何使用extends关键字的CZ与绘制图形有兟뀂与其不同的是,此处H门所用的CZ用SwinglgQ以便你不必创徏额外的新cR在一个非常有限的例子中,Swing按钮lg的类层次l构如下所C,当然QObject是实际上的根?br />
Component
|- Container
|- JComponent
|- AbstractButton
|- JButton
|- JMenuItem
|- JCheckBoxMenuItem
|- JMenu
|- JRadioButtonMenuItem
|- JToggleButton
|- JCheckBox
|- JRadioButton
所有AbstractButton的子c都共同享有的一个东西就是方法getText。这是泛型的精髓,你能定义一个方法去处理以AbstractButton为元素的ListQƈq回q些按钮的Stringcd的标{List。下面是该方法的W一个版本:
public static List<String> getLabels(List<AbstractButton> list) {
List<String> labelList = new ArrayList<String>(list.size());
for (AbstractButton button: list) {
labelList.add(button.getText());
}
return labelList;
}
下面是如何使用该方法。首先,定义一个AbstractButtoncd的ListQ然后向其中填充|q调用该ҎQ?br />
List<AbstractButton> buttonList = new ArrayList<AbstractButton>();
buttonList.add(new JButton("Hello"));
buttonList.add(new JCheckBox("World"));
buttonList.add(new JRadioButton("Hola"));
buttonList.add(new JMenuItem("Mundo"));
List labels = getLabels(buttonList);
System.out.println(labels);
ҎGoogleQ?Hola, Mundo"?Hello, World"的西班牙译文。调用println()Ҏ的结果如下所C:
[Hello, World, Hola, Mundo]
对于AbstractButton?span style="font-family: Courier;">List对象Q一切都能正常运行,但当是其它类型,特别是AbstractButton子类型的ListӞ׃能正常工作了。从逻辑上,有h可能认ؓ对于以JButton为元素的ListQ一切仍能正常工作。因为JButton是AbstractButton的子cR难道不能对AbstractButton子类型的List调用ҎgetLabels(List<AbstractButton>)Q?br />
然而,事实q如此。因是一个编译时查,同时也因为getLabelsҎ被定义ؓ只接受AbstractButton的ListQ你不能向该Ҏ中传入Q何其它类型的List?br />
GetList.java:13: getLabels(java.util.List<javax.swing.AbstractButton>)
in GetList cannot be applied to (java.util.List<javax.swing.JButton>)
List<String> labels = getLabels(buttonList);
^
1 error
q也是extends关键字发挥作用的地方了。不?span style="font-family: Courier;">getLabesҎ定义Z仅接?span style="font-family: Courier;">AbstractButton ListQ而是它定义为接?span style="font-family: Courier;">AbstractButton子类?span style="font-family: Courier;">ListQ?br />
public static List<String> getLabels(
List<? extends AbstractButton> list)
此处的通配W?表明该方法ƈ不关心确切的cd是什么,只要它是AbstractButton的子cd卛_。下面是l合了前q所有代码片断的完整CZE序Q?br />
import java.util.*;
import javax.swing.*;
public class GetList {
public static void main(String args[]) {
List<JButton> buttonList =
new ArrayList<JButton>();
buttonList.add(new JButton("Hello"));
buttonList.add(new JButton("World"));
buttonList.add(new JButton("Hola"));
buttonList.add(new JButton("Mundo"));
List labels = getLabels(buttonList);
System.out.println(labels);
}
public static List<String> getLabels(
List<? extends AbstractButton> list) {
List<String> labelList = new ArrayList<String>(list.size());
for (AbstractButton button: list) {
labelList.add(button.getText());
}
return labelList;
}
}
现在Q当你要用泛型来定义你自qcdҎӞp考虑接受作ؓ泛型参数的抽象类Q或它的M类Q记得用通配W以便相同的Ҏ对于子类也能很好地工作?br />
更多关于泛型的信息,误两篇较早前由Gilad Bracha撰写的教E:一是2004q的教程(PDF)Q另一是在线?a >Java Tutorial中的泛型章节?br />

]]>