【Java开发语言 08】第八章 泛型(为什么使用泛型+泛型的使用+泛型类+泛型接口,(未)传入泛型实参+泛型方法+通配符+泛型通配符+有限制的通配符)

为什么使用泛型

在这里插入图片描述

  • 例如:未规定泛型时,ArrayList可以存放String类和Integer类型的元素;但规定泛型为String时,就只可以存储String类型的元素(图中为编译器发现的问题)
    在这里插入图片描述
  • 泛型只在编译阶段有效
    在这里插入图片描述

泛型的使用

泛型类

在这里插入图片描述

  • 示例:泛型类,实例化对象时,指定不同的泛型
public class A<T> {
    private T key;

    public void setKey(T key ){
        this.key = key;
    }
    
    public T getKey(){
        return this.key;
    }

    public static void main(String[] args){
        //----------------------------------------
        A<String > a1 = new A<String>();
        a1.setKey("xxx");
        String s = a1.getKey();
        
        //----------------------------------------
        A<Integer> a2 = new A<Integer>();
        a2.setKey(1);
        Integer i = a2.getKey();
        
        //----------------------------------------
        A a3 = new A();//相当于A<Object> a3 = new A<Obiect>();
        a3.setKey("hello");//或者a3.setKey(new Object());
        a3.setKey(896);
        Object obj = a3.getKey();//896
    }
}

注: 同样的类,但是在new对象时,泛型指定不同的数据类型,这些对象不能互相赋值

  • 示例:泛型类构造器不可带泛型
public static class DNode<T>{
        public T value;
        public DNode<T> last;
        public DNode<T> next;
        public DNode(T data){
            value = data;
        }
    }

泛型接口

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 泛型接口IB,类B1,B2继承接口。其中B1不指定泛型,类加泛型声明;B2继承时指定接口泛型
public class TestIB {
    public static void main(String[] args) {
    
        //B1和B2类的使用区别
        B1 b1 = new B1();//相当于B1<Object> b1 = new B1();
        B1<String> b2 = new B1();
        B1<Integer> b3 = new B1();

        B2 b4 = new B2();//不用指定泛型,因为已经确定为String

        b1.test(new Object());
        b1.test("yurt");
        b1.test(45634);
        
        b2.test("453rt");
        b3.test(876);
        b4.test("ryut");
    }
}


interface IB<T> {

    public T test (T t);
}

/**
 * @Description: 未传入泛型实参,声明类时,泛型声明一起加到类中
 */
class B1<T> implements IB<T>{
    @Override
    public T test(T t) {
        return null;
    }
}

/**
 * @Description: 传入泛型实参String,如果实现接口时指定接口的泛型的具体数据类型,
 * 这个类实现接口所有方法的位置,都要泛型替换实际的具体数据类型
 */
class B2 implements IB<String>{

    @Override
    public String test(String s) {
        return null;
    }
}

泛型方法

泛型方法,在调用时确定泛型具体数据类型

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: xuexuezi
 * @Date: 2022/11/10/23:28
 * @Description: 测试泛型方法
 */
public class C<E> {
    /*在类中可定义泛型变量,可在普通方法内使用
    但不能在static静态方法中使用,如果要使用泛型,只能使用静态方法自己定义的泛型
    */

    private E e;

    //此处方法的泛型化都属于方法的重载,因为同名且参数不同;注意判断方法是否重载与返回值无关
    //==========================无返回值的方法泛型化=========================
    public void test(){
        System.out.println(this.e);//可以使用泛型变量
    }
    //将public void test();泛型化
    public<T> void test(T s){
        T t = s;
        System.out.println(this.e);//可以使用泛型变量
    }

    //==========================有返回值的方法泛型化==========================
    public String test1(String s){

        return s;
    }

    //泛型化
    public<T> T test1(T s){//与test中的T在一个类中不冲突,属于方法内的定义
        return s;
    }

    //==================无返回值,可变参数类型的方法泛型化=====================
    public void test2(String... strs){//与数组做参数使用方法相同,传参可以传数组名,new匿名数组,直接传元素串
        for(String s: strs){
            System.out.println(s);
        }
    }
    //泛型化
    public<T> void test2(T... strs){
        for(T s: strs){
            System.out.println(s);
        }
    }

    //=======================静态的方法泛型化===========================
    public static void test3(int i){
        System.out.println(i);
    }
    //泛型化
    public static<T> void test3(T t){
        System.out.println(t);
        //System.out.println(e);//类定义的泛型变量,静态方法不可用
    }

    //========================方法的使用=============================
    public static void main(String[] args) {
        /*泛型方法在调用之前没有固定的数据类型,在调用时,传入的参数是什么类型,就会把泛型改成什么类型*/
        C<Object> c = new C<Object>();//<Object>不可省略
        Integer ii = c.test1(2);//传入的参数是Integer,泛型就固定成Integer,返回值就是Integer
        Boolean b = c.test1(true);//传入的参数是Boolean,泛型就固定成Boolean,返回值就是Boolean
        c.test();
        C.test3(false);
    }
}

注: 泛型方法使用时,不指定泛型的情况<Object>不可省略;但继承泛型接口且继承时不指定泛型的类泛型类使用时不指定泛型的情况,可以省略<Object>

通配符

泛型通配符

在这里插入图片描述

  • 方法参数不确定集合List的数据类型,用?代替。传参时,向?传入数据类型来规定集合数据类型
public class WildCard {
    public void test(List<?> list){//需要一个list参数,但不确定数据类型
        Iterator<?> it = list.iterator();
        while(it.hasNext()){
            System.out.println(it.next());
        }

    }

    public static void main(String[] args){
        WildCard d = new WildCard();
        List<String> l1 = new ArrayList<String>();
        l1.add("rtury");
        l1.add("45terw");
        List<Integer> l2 = new ArrayList<Integer>();
        l2.add(45);
        l2.add(564);
        l2.add(3456);
        d.test(l1);
        d.test(l2);
    }

}

有限制的通配符

在这里插入图片描述

  • 有限制的通配符,定义类的继承关系:Aa->Bb->Cc->Dd;B1和B2类实现接口IB
  • 定义三个方法的参数限制
  • List<? extends Cc> list只允许泛型为C及C的子类的引用调用
  • Set<? super Bb> set只允许泛型为TestIB及TestIB父类的引用调用
  • List<? extends IB> list只允许泛型为实现IB接口的实现类引用调用
import java.util.*;
/**
 * Created with IntelliJ IDEA.
 *
 * @Author: xuexuezi
 * @Date: 2022/11/11/4:47
 * @Description: 有限制的通配符,定义类的继承关系:Aa->Bb->Cc->Dd,B1和B2类实现接口IB
 */
class Aa{
}
class Bb extends Aa{

}class Cc extends Bb{
}
public class Dd extends Cc{
    public void test(List<? extends Cc> list){//只允许泛型为C及C的子类的引用调用
        Iterator<?> it = list.iterator();
        while(it.hasNext()){
            System.out.println(it.next());
        }
    }
    public void test2(Set<? super Bb> set){//只允许泛型为TestIB及TestIB父类的引用调用
        Iterator<?> it = set.iterator();
        while(it.hasNext()){
            System.out.println(it.next());
        }
    }
    public void test3(List<? extends IB> list){//只允许泛型为实现IB接口的实现类引用调用
        Iterator<?> it = list.iterator();
        while(it.hasNext()){
            System.out.println(it.next());
        }
    }

    public static void main(String[] args) {
        Dd d = new Dd();
        List<Aa> la = new ArrayList<>();
        List<Bb> lb = new ArrayList<>();
        List<B1> lb1 = new ArrayList<>();
        List<Cc> lc = new ArrayList<>();
        List<Dd> ld = new ArrayList<>();

        Set<Aa> sa = new HashSet<>();
        Set<Bb> sb = new HashSet<>();
        Set<Cc> sc = new HashSet<>();
        Set<Dd> sd = new HashSet<>();


        //==========================调用test,list泛型为C及C的子类的引用调用=====================

        System.out.println("调用test,list泛型为C及C的子类的引用调用");
        d.test(lc);
        d.test(ld);
        //d.test(lb1);
        //====================调用test2,set泛型为TestIB及TestIB父类的引用调用==================
        System.out.println("调用test2,set泛型为TestIB及TestIB父类的引用调用");
        d.test2(sa);
        d.test2(sb);
        //d.test2(sc);
        //d.test2(sd);
        //====================调用test3,list泛型为实现IB接口的实现类引用调用=====================
        System.out.println("调用test3,list泛型为实现IB接口的实现类引用调用");
        //d.test3(la);
        //d.test3(lb);
        d.test3(lb1);
        //d.test3(lc);

    }

}

  • 测试结果,不符合通配符条件的参数,编译报错
    在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值