Java泛型之上界为其他类型参数引起的情况分析(观Java编程逻辑有感)

2023-05-16

文章目录

  • 普通版
  • 解析通配符
    • 区别
    • 注意点

终有一天,我还是来补《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);
//        System.out.println(number);
        
    }

}

想要实现的事情很简单:
就是在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(使用前将#替换为@)

Java泛型之上界为其他类型参数引起的情况分析(观Java编程逻辑有感) 的相关文章

随机推荐