java泛型方法使用通配符还是类型参数总结+两者之间的关系

2023-05-16

文章目录

  • 准备工作 🦘
  • 玩x1 🐒
  • 玩x2 🐈
  • 玩x3 🐕
  • 总结 🐾

准备工作 🦘

依旧是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 <T extends E> void addAll(DynamicArray<T> 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 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;
    }

}

玩x1 🐒

按常理来说,通配符能够使用的场合,就一定可以转换成类型参数的形式。
上篇博客的末尾内容:

public int indexOf(DynamicArray<? > arr, Object e)

效果等同于:

public <T> int indexOf(DynamicArray<T> 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()方法是非法的,但是同样的内部主体代码,如果说我改成了借助类型参数的泛型方法又会怎么样呢?

    public <T> void swapInternal(DynamicArray<T> 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);
    }

编译器并没有报错!测试一下
在这里插入图片描述
可以看到顺序成功的调换了!
这种情况称为“需要写的场合”,这种场合显然是不能够使用通配符的,因为使用通配符的地方只能“读”,你现在的做法显然是要“移动”元素,不是简单的读,那么必然报错

玩x2 🐈

如果参数类型之间存在“依赖关系”,常用的就是extends,那么这种时候也只能够使用类型参数
,比如我现在想把src容器中的内容搞到dest容器(注意此时src容器的类型变量必须是dest容器的子类,这里明显有一个继承关系)
这里我觉得很好理解,如果使用通配符,如果两个都是使用通配符,那么肯定存在安全隐患,肯定报错,这里显示正确版本,即使用类型参数的泛型方法

    public static <D,S extends D> void copy(DynamicArray<D> dest, DynamicArray<S> src){
        for (int i = 0; i < src.size(); i++) {
            dest.add(src.get(i));
        }
    }

这里也可以这样玩儿:

    public static <D> void copy(DynamicArray<D> 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<T> {

    public int compareTo(T o);

}

总结 🐾

最后,那就是我们在使用的时候,很经常将这两者一起结合使用,就像上面的copy方法一样,定义必要的类型参数,使用通配符表达依赖,并接受更广泛的数据类型。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

java泛型方法使用通配符还是类型参数总结+两者之间的关系 的相关文章

随机推荐