关于java泛型方法设定通配符的下限,求高手看我理解是不是正确

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于java泛型方法设定通配符的下限,求高手看我理解是不是正确相关的知识,希望对你有一定的参考价值。

//继test84类之后
/*
假设该方法需要返回一个值,返回最后一个被复制的元素
*/
//实现一个工具方法,实现将src集合里的全部元素复制到dest集合里
import java.util.Collection;
import java.util.ArrayList;
public class test84_1

public static <E> E test(Collection<? extends E> src,Collection<E> dest)


E last=null;
for(E s:src)

dest.add(s);
last=s;

return last;


public static void main(String[] args)

Collection<Integer> src=new ArrayList<Integer>();
src.add(78);
Collection<Number> dest=new ArrayList<Number>();
/*
上面看上去没有任何问题,可是下面编译错误,不兼容类型,
为什么会这样呢??
因为src在迭代的过程中丢失了集合元素的类型,
可以简单的去理解, 你传递过去对应的E是什么类型,你返回的就是什么类型
怎么解决这个问题呢? 请看下节, 通配符下限
*/
Integer I=test84_1.test(src,dest);
System.out.println(I);




//通配符下限
import java.util.Collection;
import java.util.ArrayList;
public class test84_2

public static <R> R test(Collection<R> src,Collection<? super R> dest)


R last=null;
for(R s:src)

last=s;
dest.add(s);

return last;


public static void main(String[] args)

Collection<Integer> src =new ArrayList<Integer>();
Collection<Number> dest=new ArrayList<Number>();
src.add(78);
Integer i= test84_2.test(src,dest);
System.out.println(i);




/*
以下是我对通配符下限的自我理解 ,先不要去看上面的下限也好 上限也好的...秒死没有上限
其实下限就是把两个集合的位置换一下 使它能存放Integer类型的数据
原本test84_1里的文件,它最后是不能存放Integer类型的, 它返回的是Number类型的, 除非是它的父类 或者同类
一般来说<? extends R>dest这样的形式, dest.add("这样是不能存入数据的,未知类型,报错的");
然而,使用通配符下限的方法 就可以实现上面不能存数据的问题, 这样就能把最后返回的那个数据类型变了,
*/

你第二种之所以不报错,是因为方向对了,
1的E不一定能转换成?
但是2的?一定可一转换成R
参考技术A Collection<? extends E> src
Collection<? super R> dest

你想说什么呢 没看明白 说清楚点一起研究哈
参考技术B 黑兔

Java泛型详解

泛型类及其方法

  1. 泛型定义在类名上, ,T 可以是任意字符如A、B、C。
  2. 类中的方法(普通方法、静态方法、构造方法)可以使用类的泛型T。
package com.example.demo;


import lombok.Data;

import java.util.Collections;
import java.util.List;
import java.util.Set;

/**
 * @author CCL
 * @createTime 2021年12月24日
 */
@Data
public class Demo1<T> 
    private int age;
    private T a;

    public Demo1(int age, T a) 
        this.age = age;
        this.a = a;
    

    /**
     * 入参为泛型,出参为void
     */
    public void call(T a) 
        this.a = a;
        System.out.println(a);
    

    /**
     * 入参为泛型,出参为特定类型
     */
    public String say(T a) 
        return a.toString();
    

    /**
     * 入参为泛型,出参为泛型,List<T>为出参类型
     */
    public List<T> cry(T a) 
        return Collections.singletonList(a);
    

    /**
     * 入参为泛型,出参为泛型
     *
     * @param set
     * @return
     */
    public List<T> cry(Set<T> set) 
        return Collections.singletonList(set.iterator().next());
    

    /**
     * 用<>表示的方法才是泛型方法,否则只能是使用了类泛型的方法
     * @param e
     * @param t
     * @param <E>
     */
    public <E> void fun1(E e,T t)
        System.out.println(e.toString());
        System.out.println(t.toString());
    

普通类中的泛型方法

  1. 类可以没有泛型。
  2. 方法必须在公开符和返回参数之间用 标识这是一个泛型方法。
import java.util.Collections;
import java.util.List;

public class Demo2 
    //泛型作为入参
    public <E> void fun1(E t)
        System.out.println(t.toString());
    
    //有返回值的泛型
    public <E> List<E> fun2(E t)
        return Collections.singletonList(t);
    
    //多个泛型
    public <E,T> List<E> fun2(E e,T t)
        System.out.println(e);
        System.out.println(t);
        return Collections.singletonList(e);
    

泛型的范围限定

1. 用泛型限定T只能是某个类的子类

示例1:用在类上,并泛型调用方法

public class Demo3<T extends Number> 

    public void demo(T t)
        System.out.println(t.intValue());
    

    public static void main(String[] args) 
        Demo3<Long> demo3 = new Demo3<>();
        Long size = 4L;
        demo3.demo(size);
    

示例2:用在集合上,可以get,get出来的使用泛型指定的父类型来接收。但add时无论什么类型都会报错。

public class Demo4
    public static void main(String[] args) 

        List<? extends Number> list= new ArrayList<>();
        List<String> strList = Arrays.asList("a", "b");
        List<Integer> intList = Arrays.asList(1, 2);
        //Integer为Number的子类型,赋值正常
        list=intList;
        //String的List在编译时会报错
        list=strList;
    

示例3:


    public void play()
        //这里赋值没问题
        List<? extends A> list = Arrays.asList(new A(), new B(), new C());
        //取出可以
        A a0 = list.get(0);
        A a1 = list.get(1);
        A a2 = list.get(2);
        //下面所有add编译报错,因为
        list.add(new A());
        list.add(new B());
        list.add(new C());
        list.add(new Object());

    

2. 限定下限

用泛型设定?只能是指定类型及其父类。
用在集合上时,可以add指定类型及其父类,get时只能用Object接收。

class A 
class B extends A
class C extends B
    public static void main(String[] args) 
        List<? super B> list = new ArrayList<>();
        list.add(new A());//报错,只能add B及其父类
        list.add(new B());
        list.add(new C());
        System.out.println(list);
        //get出的类型为Object
        Object object = list.get(0);

    

3.无限定通配符

无限定通配符表示不需要限定任何类型。

 class PairAlg 
     public  boolean play(List<?> p) 
         return p.get(0) == null || p.get(1) == null;
     
    public static boolean hasNulls(List<?> p) 
        return p.get(0) == null || p.get(1) == null;
    

以上是关于关于java泛型方法设定通配符的下限,求高手看我理解是不是正确的主要内容,如果未能解决你的问题,请参考以下文章

java泛型上限下限,通配符

java泛型上限下限,通配符

JAVA泛型之<? extends T>:(通配符上限)和<? super T>(通配符下限)

Java 泛型通配符上限和通配符下限(正在整理)

泛型-类型通配符的下限

Java 泛型概述与应用