准备工作 輦玩x1 玩x2 玩x3 总结
准备工作 輦依旧是DynamicArray的例子,继续上一篇博客
package com.xmonster.demo2; import java.util.Arrays; public class DynamicArray玩x1 { private static final int DEFAULT_CAPACITY = 10; private int size = 0; private Object[] elementData; public DynamicArray(){ this.elementData = new Object[DEFAULT_CAPACITY]; } private void ensureCapacity(int minCapacity){ int oldCapacity = elementData.length; if(oldCapacity >= minCapacity){ return; } int newCapacity = oldCapacity * 2; if(newCapacity < minCapacity){ newCapacity =minCapacity; } elementData = Arrays.copyOf(elementData, newCapacity); } public void add(E e){ ensureCapacity(size+1); elementData[size++]=e; } public E get(int index){ return (E)elementData[index]; } public int size(){ return size; } public E set(int index, E element){ E oldValue = get(index); elementData[index] = element; return oldValue; } // public void addAll(DynamicArray c){ // for (int i = 0; i < c.size; i++) { // add(c.get(i)); // } // } public void addAll(DynamicArray extends E> c){ for (int i = 0; i < c.size; i++) { add(c.get(i)); } } public static > T max(T[] arr){ T max=arr[0]; for (int i = 0; i < arr.length; i++) { if(arr[i].compareTo(max)>0){ max=arr[i]; } } return max; } }
按常理来说,通配符能够使用的场合,就一定可以转换成类型参数的形式。
上篇博客的末尾内容:
public int indexOf(DynamicArray > arr, Object e)
效果等同于:
publicint indexOf(DynamicArray arr, Object e)
但是,别忘了,使用通配符只能读,不能写
这里又有一种情况,那就是最简单的数组中两者交换位置的操作,这个操作可以理解成:
public void swap(DynamicArray > arr, int i, int j){
Object tmp = arr.get(i);
arr.set(i, arr.get(j));
arr.set(j, tmp);
}
这段代码按常理来说确实没什么问题,但是事实是:
编译器直接报错了!错误原因:
它很明显,它想让我转换类型,如果使用通配符?来表示的话显然不行了,因为这两种set()方法是非法的,但是同样的内部主体代码,如果说我改成了借助类型参数的泛型方法又会怎么样呢?
publicvoid swapInternal(DynamicArray arr, int i, int j){ T tmp = arr.get(i); arr.set(i, arr.get(j)); arr.set(j, tmp); } public void swap(DynamicArray > arr, int i, int j){ swapInternal(arr, i, j); }
编译器并没有报错!测试一下
可以看到顺序成功的调换了!
这种情况称为“需要写的场合”,这种场合显然是不能够使用通配符的,因为使用通配符的地方只能“读”,你现在的做法显然是要“移动”元素,不是简单的读,那么必然报错
如果参数类型之间存在“依赖关系”,常用的就是extends,那么这种时候也只能够使用类型参数
,比如我现在想把src容器中的内容搞到dest容器(注意此时src容器的类型变量必须是dest容器的子类,这里明显有一个继承关系)
这里我觉得很好理解,如果使用通配符,如果两个都是使用通配符,那么肯定存在安全隐患,肯定报错,这里显示正确版本,即使用类型参数的泛型方法
public staticvoid copy(DynamicArray dest, DynamicArray src){ for (int i = 0; i < src.size(); i++) { dest.add(src.get(i)); } }
这里也可以这样玩儿:
public staticvoid copy(DynamicArray dest, DynamicArray extends D> src){ for (int i = 0; i < src.size(); i++) { dest.add(src.get(i)); } }
可以理解成“简约”版本
玩x3 还有一种情况:那就是返回值依赖于类型参数时,肯定也是不能使用通配符,这里没什么好说了,可以参考上面DynamicArray的最后一个方法,是一个求最大值的方法,那个方法就是典型例子。
这里提供Comparable接口:
package com.xmonster.demo2; public interface Comparable总结 { public int compareTo(T o); }
最后,那就是我们在使用的时候,很经常将这两者一起结合使用,就像上面的copy方法一样,定义必要的类型参数,使用通配符表达依赖,并接受更广泛的数据类型。



