终有一天,我还是来补《Java编程逻辑》,这本书写的非常好,以下是我阅读到泛型这一板块遇到的一些特殊情况的记录,有问题欢迎指正!
普通版
这是DynamicArray类,粗略实现动态数组:
package com.xmonster.demo2;
import java.util.Arrays;
public class DynamicArray<E> {
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<E> c){
for (int i = 0; i < c.size; i++) {
add(c.get(i));
}
}
public static <T extends Comparable<T>> 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;
}
}
测试
import com.xmonster.demo2.DynamicArray;
import com.xmonster.demo2.NumberPair;
import com.xmonster.demo2.Pair;
import org.junit.Test;
import java.util.Random;
public class PairTest {
public static void main(String[] args) {
DynamicArray<Number> number = new DynamicArray<>();
DynamicArray<Integer> ins = new DynamicArray<>();
ins.add(1);
ins.add(3);
number.addAll(ins);
}
}
想要实现的事情很简单:
就是在DynamicArray类增加了一个addAll方法,这个方法将参数容器中的所有元素都增加到当前容器来。
分析现状:
number是一个Number类型的容器,ins是一个Integer类型的容器,我想要将ins添加到number中,因为Integer是Number的子类,这原本应该是一个合理的需求操作
但是,在编译器上:
提示话语:
🔺🔺在这里的提示应该已经很明显了!虽然说Integer是Number的子类,但是DynamicArray又不是DynamicArray的子类呀!DynamicArray不能赋值给DynamicArray的变量
继续回到上面的需求,修改代码为:
public <T extends E> void addAll(DynamicArray<T> c){
for (int i = 0; i < c.size; i++) {
add(c.get(i));
}
}
可以发现不再报错,T的上界限定为E。
解析通配符
上面,我们的类型参数使用了其他类型参数作为上界,那么换种简洁写法:
public void addAll(DynamicArray<? extends E> c){
for (int i = 0; i < c.size; i++) {
add(c.get(i));
}
}
<? extends E>
表示有限定通配符,匹配E或者E的某个子类型,具体什么子类型未知
和上面的<T extends E>
有什么区别呢?
区别
<T extends E>
用于定义类型参数
,他声明了一个类型参数T,可以放在泛型类型中类名后面、泛型方法返回值前面<? extends E>
用于实例化类型参数
,它用于实例化泛型变量中的类型参数,只是这个具体的类型参数是未知的,只知道是E或者E的某个子类型
注意点
形如DynamicArray<? >这种形式称为“无限定通配符”,这种写法也是可以转换成使用类型参数的形式就像上面的一样,比如:
public int indexOf(DynamicArray<? > arr, Object e)
效果等同于:
public <T> int indexOf(DynamicArray<T> arr, Object e)
但是,别忘了,使用通配符只能读,不能写
因为使用 ? 就意味着类型的安全性是未知的!不知道它到底指的是什么,如果允许写入,Java无法确保类型安全性,直接就禁止了这种写法。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)