最近在网上看到这个文章,是关于一个范型的疑惑:
网址:http://java.vkfz.com/-t153...
内容引用如下
bryantd 发表于 2006-4-19 11:39:36
我下载了JDK1.5文档中推荐的范型学习材料《generic_toturial》
其中有关讲“有界限的通配符问题”的时候,遇到了一点困惑:
Collection> c = new ArrayList();
c.add(new Object()); // compile time error
关于这段代码,我是这样理解的:由于?是actual parameter,取代了formal parameter type:E,它表示未知的类型,Collection.add(E 0){……}则必须将一个确定类型的对象参数传递给add方法,所以这样是不安全的。
public void addRectangle(List extends Shape> shapes) {
shapes.add(0, new Rectangle()); // compile-time error!
}
关于这段代码,也比较好理解,由于 extends Shape>表示Shape类型的一个未知子类型,其不能保证是Rectangle的超类,所以向shapes中添加Rectangle是不安全的,编译器禁止。
但是接下来的一个例子让我不太理解:
public class Census {
public static void addRegistry(Map registry) { ...}
}...
Map allDrivers = ...;
Census.addRegistry(allDrivers);
按照上面那个例子的说法,? extends Person不也不能保证是Driver的超类吗?为什么这里就可以了?
这个例子的英文原文如下:
Bounded wildcards are just what one needs to handle the example of the DMV
passing its data to the census bureau. Our example assumes that the data is represented
by mapping from names (represented as strings) to people (represented by reference
types such as Person or its subtypes, such as Driver). Map is an example of
a generic type that takes two type arguments, representing the keys and values of the
map.
Again, note the naming convention for formal type parameters - K for keys and V
for values.
public class Census { public static void
addRegistry(Map registry) { ...}
}...
Map allDrivers = ...;
Census.addRegistry(allDrivers);
这个问题是个比较容易混淆的概念,其实很多时候,这种问题往往会越搞越糊涂,
其实如果仔细的分析一下,会发现这两个问题本身就不是一个概念。
简单的说吧,作者是把两个概念混在一起看了,于是便多少有些看不清楚。
不如我们把这两个问题用一个事件联系起来,看看区别到底在什么地方。
假设我们现在有两个接口:杯子和球,杯子就是容器,球就是要装入容器的对象,
那么上述的两个问题就能按照这个概念来理解:
程序1:
public void add球(容器 extends 杯子> 实例化杯子) {
实例化杯子.add(0, new 篮球());// compile-time error!
}
程序2
public class 普通水杯杯口直径5cm{
public static void add球(球<品牌, ? extends 直径小于5cm的球> 实例化的球) { ...}
}...
球<品牌, 乒乓球> 球的实例= ...;
普通水杯杯口直径5cm.addRegistry(球的实例);
仔细理解一下,就能发现,问题就在于,
程序1里面你要传入的是一个容器,这个容器只要是杯子的子类就可以,
但是却试图在方法体里面往杯子里面塞一个篮球,那么有人觉得这个安全么?编译当然不给通过了。
而程序2,在方法里面只是试图往一个普通水杯里面塞球,这个球已经限制了条件,
就是比杯口小的任何球,随你是乒乓球,弹珠球还是高尔夫球。
那么,无论如何,这个杯口是5cm的杯子显然是有乘在能力的,放入这个球,绝对安全。
其实说白了,这个问题就在于,前者你往一个容器的子类里面塞大东西,这个容器你并不知道承载力,
后者你往一个限定了承载力的容器里面放入最大承载力对象的子类。
传入参数概念不通,当然结果就不通。
网址:http://java.vkfz.com/-t153...
内容引用如下
引用
bryantd 发表于 2006-4-19 11:39:36
我下载了JDK1.5文档中推荐的范型学习材料《generic_toturial》
其中有关讲“有界限的通配符问题”的时候,遇到了一点困惑:
Collection> c = new ArrayList
c.add(new Object()); // compile time error
关于这段代码,我是这样理解的:由于?是actual parameter,取代了formal parameter type:E,它表示未知的类型,Collection.add(E 0){……}则必须将一个确定类型的对象参数传递给add方法,所以这样是不安全的。
public void addRectangle(List extends Shape> shapes) {
shapes.add(0, new Rectangle()); // compile-time error!
}
关于这段代码,也比较好理解,由于 extends Shape>表示Shape类型的一个未知子类型,其不能保证是Rectangle的超类,所以向shapes中添加Rectangle是不安全的,编译器禁止。
但是接下来的一个例子让我不太理解:
public class Census {
public static void addRegistry(Map
}...
Map
Census.addRegistry(allDrivers);
按照上面那个例子的说法,? extends Person不也不能保证是Driver的超类吗?为什么这里就可以了?
这个例子的英文原文如下:
Bounded wildcards are just what one needs to handle the example of the DMV
passing its data to the census bureau. Our example assumes that the data is represented
by mapping from names (represented as strings) to people (represented by reference
types such as Person or its subtypes, such as Driver). Map
a generic type that takes two type arguments, representing the keys and values of the
map.
Again, note the naming convention for formal type parameters - K for keys and V
for values.
public class Census { public static void
addRegistry(Map
}...
Map
Census.addRegistry(allDrivers);
这个问题是个比较容易混淆的概念,其实很多时候,这种问题往往会越搞越糊涂,
其实如果仔细的分析一下,会发现这两个问题本身就不是一个概念。
简单的说吧,作者是把两个概念混在一起看了,于是便多少有些看不清楚。
不如我们把这两个问题用一个事件联系起来,看看区别到底在什么地方。
假设我们现在有两个接口:杯子和球,杯子就是容器,球就是要装入容器的对象,
那么上述的两个问题就能按照这个概念来理解:
程序1:
public void add球(容器 extends 杯子> 实例化杯子) {
实例化杯子.add(0, new 篮球());// compile-time error!
}
程序2
public class 普通水杯杯口直径5cm{
public static void add球(球<品牌, ? extends 直径小于5cm的球> 实例化的球) { ...}
}...
球<品牌, 乒乓球> 球的实例= ...;
普通水杯杯口直径5cm.addRegistry(球的实例);
仔细理解一下,就能发现,问题就在于,
程序1里面你要传入的是一个容器,这个容器只要是杯子的子类就可以,
但是却试图在方法体里面往杯子里面塞一个篮球,那么有人觉得这个安全么?编译当然不给通过了。
而程序2,在方法里面只是试图往一个普通水杯里面塞球,这个球已经限制了条件,
就是比杯口小的任何球,随你是乒乓球,弹珠球还是高尔夫球。
那么,无论如何,这个杯口是5cm的杯子显然是有乘在能力的,放入这个球,绝对安全。
其实说白了,这个问题就在于,前者你往一个容器的子类里面塞大东西,这个容器你并不知道承载力,
后者你往一个限定了承载力的容器里面放入最大承载力对象的子类。
传入参数概念不通,当然结果就不通。
这个人工只能nb啊,我无语了
象素字体的使用规则

2006/06/05 13:17 | by 