Java和C++在细节上的差异(四)(四)

2014-11-24 02:04:05 · 作者: · 浏览: 3
Pair rawType = manager;
4 rawType.setFirst("Hello"); //only compilation warning, but will encounter runtime error.
5 }

4) 如果public class ArrayList extends List {}, 那么从ArrayList到List的赋值是允许的,这一点和普通类型是一致的,该规则同样适用于C++
8. 泛型类型的通配符类型:该泛型特征在标准C++中完全不被支持,C#中存在类似的特征。见以下代码:
1) 子类型限定:

1 publicclassManager extendsEmployee {}
2
3 publicstaticvoidprintBuddies(Pair p) {
4 }
5
6 publicstaticvoidmain(String[] args) {
7 printBuddies(newPair()); //legal
8 printBuddies(newPair()); //illegal;
9 }

但是如果将printBuddies改为:void printBuddies(Pair< extends Employee> p),上例中main函数将可以通过编译。< extends Employee>的语义为所有Employee的子类都可以做printBuddies函数参数的类型参数。对于7-1)中的示例代码,如果改为通配符类型将可以通过编译并正常运行,但是仍然存在一定的限制,见如下代码:

1 publicvoidtest() {
2 Pair manager = newPair();
3 Pair< extendsEmployee> employee = manager; //legal here.
4 //由于otherEmployeeButNotManager虽为Employee子类,但可能并非Manager类,
5 //由于setFirst的参数将会声明为void setFirst( extends Employee),由于
6 //编译器无法确定setFirst参数的实际类型,因此将会直接报告编译错误。
7 employee.setFirst(otherEmployeeButNotManager); //compilation error
8 }

和setFirst相比,getFirst将会正常编译并运行,因为返回值无论是什么子类型,都不会带来影响和破坏。
2) 超类型限定:Pair< super Manager>表示参数类型一定是Manager的超类。因此和子类型限定刚好相反,setFirst将是合法的,而getFirst将会产生编译错误。
3) 无限定通配符,如Pair< >,该泛型类型的setFirst( )方法不能被调用,即便传入的参数是Object,这样是Pair< >和Pair之间最大的差异。该方法还有一个比较重要的作用就是用于提示泛型函数的调用者,该泛型函数更期望参数是带有类型参数的泛型类型,而不是原始类型,即便原始类型也可能正常的工作,见如下代码:

1 publicclassTestMain {
2 @SuppressWarnings("unchecked")
3 //public static T print(MyClass myclass),同样可以正常的工作,
4 //但是会有编译警告产生。
5 publicstatic T print(MyClass< > myclass) {
6 myclass.print();
7 return(T)myclass.get();
8 }
9
10 publicstaticvoidmain(String[] args) {
11 Integer ii = newInteger(5);
12 print(newMyClass(ii));
13 }
14 }
15
16 classMyClass {
17 publicMyClass(T t) {
18 _t = t;
19 }
20 T get() { return_t;}
21
22 publicvoidprint() {
23 System.out.println(_t);
24 }
25 privateT _t;
26 }

九、集合:

1. Java集合类库中最重要的两个接口Collection和Map,其中Collection接口又再次划分为List和Set两大子接口,List中可以包含重复的元素,Set中则不可以。以下列举出一些常用的集合实现类,他们均分别继承自这两个接口:
1) ArrayList: 一种可以动态增长和缩减的索引序列(动态数组,类似于C++中的vector);
2) LinkedList: 一种可以在任何位置进行高效的插入和删除操作的有序序列(类似于C++中list);
3) ArrayDeque: 一种用循环数组实现的双端队列(类似于C++中的deque);
4) HastSet:一种没有重复元素的无序集合(C++的标准库中并未提供hashset集合,但是Windows的VC和Linux平台下的gcc均各自提供了hashset容器);
5) TreeSet: 一种有序集(类似于C++中的set);
6) EnumSet: 一种包含枚举类型值的集;
7) LinkedHashSet: 一种可以记住元素插入次序的集,在其内部由LinkedList负责维护插入的次序,HashSet来维护Hash;
8) HashMap:一种存储键值对关联的数据结构(C++的标准库中并未提供hashmap集合,但是Windows的VC和Linux平台下的gcc均各自提供了hashmap容器);
9) TreeMap:一种键值有序排列的映射表(类似于C++中的map);
10) EnumMap:一种键值属于枚举类型的映射表;
11) LinkedHashMap:一种可以记住键值项插入次序的映射表;
2. ArrayList:该集合的底层是通过动态数组来实现的,集合构造的时候可以指定一个初始容量,当插入的元素过多导致已有的容量不能容纳新元素是,其底层数组的容量将自动增长原有容量的1.5 倍,这样会带来一定的空间浪费,但是为了避免经常扩张而带来的性能开销,只能是用空间换取时间了。如果在容器的中间添加或者删除一个元素都将会导致后面的元素向后或向前移动一个位置,如果元素数量较多且该操作比较频繁,将会导致系统的性能降低,然而对于容器中元素的随机访问性能较好,以下为ArrayList的常用示例代码:

1 publicstaticvoidshowIterator() {
2