Java进阶:【泛型】认识泛型,泛型方法,泛型类,泛型接口和通配符

x33g5p2x  于2021-11-27 转载在 Java  
字(3.1k)|赞(0)|评价(0)|浏览(374)

泛型

什么是泛型:

泛型就相当于标签

形式:<>

jdk1.5之后,用泛型来解决元素类型不确定的数据保存操作,

例如关于这个元素如何保存,如何管理等是确定的,因此此时把元素的类型设计成一个参数,这个类型参数叫做泛型。

没有泛型的集合

public static void main(String[] args) {
        ArrayList al = new ArrayList();
        al.add(98);
        al.add(18);
        al.add(38);
        al.add(88);
        al.add("丽丽");
        for (Object o : al) {
            System.out.print(o+" ");
        }
    }

如果不使用泛型的话,有缺点:

一般我们在使用的时候基本上往集合里随意放值,因为底层是一个obj类型的数组,所以什么都能放,不方便管理。

在jdk1.5以后开始,使用泛型加入泛型的优点:在编译的时候就会对类型进行检查,不是泛型的就无法添加到这个集合

public static void main(String[] args) {
        ArrayList<Integer> al = new ArrayList();
        al.add(98);
        al.add(18);
        al.add(38);
        al.add(88);
        for (Integer o : al) {
            System.out.print(o+" ");
        }
    }

总结:

  1. JDK1.5之后
  2. 泛型实际就是一个<>引起来的参数类型,这个参数类型具体在使用的时候才会确定类型

  1. 使用了泛型后,可以确定集合的类型,在编译的时候就可以检查出来
  2. 使用泛型可能觉得麻烦,实际上使用泛型才会简单,后续的便利操作会简单许多
  3. 泛型对应的类型都是引用类型不能是基本类型

泛型类和泛型接口

声明泛型类时传入类型实参
创建泛型类对象时,传入类型实参
类型实参为空时,默认为Object类型

继承泛型类:

1.泛型父类不传入类型实参,默认为Object类型
2.泛型父类传入类型实参,子类既可以是泛型类,也可以不是
3.泛型父类传入类型实参,则子类必须是泛型类,且子类的类型形参列表必须包含父类的类型形参列表

泛型类的定义和实例化,如果实例化的时候不明确指定泛型,那么默认为Object类型

package TestGeneric.GenericTest;

public class test01<e> {
/* * 这是一个普通类 * test01<a>就是一个泛型类 * <>里面就是一个参数类型,但是这个类型是什么?,不确定,相当于一个占位 * 但是现在确定的是这个类型一定是引用类型,而不是基本类型 * */
int age;
String name;
e sex;
public void a(e n){

}
public void b(e[] n){

}
static class Test{
    public static void main(String[] args) {
    test01 gt1 = new test01();
    gt1.a("abc");
    gt1.a(17);
    gt1.a(9.8);
    gt1.b(new String[]{"a","b","A"});

        test01<String> gt2 = new test01<>();
        gt2.sex ="男";
        gt2.a("abc");
        gt2.b(new String[]{"a","b","A"});
    }

}
}
继承:父类指定泛型接口

当父类指定了泛型类型,子类就不许要再指定了,可以直接使用

static class SubGeneric extends test01<Integer>{

}

static class Demo{
    public static void main(String[] args) {
            SubGeneric sgt = new SubGeneric();
                sgt.a(19);
    }
}
继承:父类不指定

如果父类不指定泛型,那么子类在实例化的时候需要指定

static class SubGeneric2<e> extends test01<e>{
            
    }

泛型类可以定义多个参数类型

泛型类的构造器写法:

不同泛型的引用类型不可以互相赋值

泛型如果不指定,就会被擦除,例子就是

泛型类中的静态方法不能使用类的泛型

不能直接使用泛型数组的创建,如果非要创建

泛型方法

  1. 什么是泛型方法,不是带泛型的方法就是泛型方法,泛型方法有要求:这个方法的泛型参数类型要和当前类的泛型方法的泛型无关
  2. 换个角度:泛型方法对应的那个泛型参数类型和当前所在的这个类,是否为泛型类,泛型是啥,无关
  3. 泛型方法定义的时候,前面要加上t,原因如果不加的话,会把t当作一种数据类型,然而代码中没有t类型那么就会报错
  4. t的类型实在调用方法的时候确定的
  5. 泛型方法是否是静态方法?可以是

代码类型:

public class test02<e> {
    public  void a(e e){

    }
    public static <T>  void b(T t){

    }

static class Demo{
    public static void main(String[] args) {
        test02<String> t2 = new test02();
        t2.a("1");
        t2.b("abc");
    }
}

泛型参数存在继承的情况

前面两个引用类型,都可以赋值,为什么list不行?

其实我们用的Arraylist,他的底层是一个Obj类型的数组,我们的泛型负责在编译的时候限制类型,

例子:两个类,a,b两类,a是b的父类,两者是继承关系,但是 G ,G两者不存在继承关系,应为他们都是引用Arraylist所以是同级关系

通配符

当我想要重载不同泛型的list时,常见的重载无法让我们完成需求,于是我们需要通配符

在没有通配符的情况下,下面a方法,相当于重复定义

通配符是什么?

发现:两个类,a,b两类,a是b的父类,两者是继承关系,但是 G< a> ,G< b>两者不存在继承关系,应为他们都是引用Arraylist所以是同级关系但是使用了通配符后,我们发现G<?>变成了G< a> ,G< b>的父类

使用通配符

无边界通配符( ?),固定上边界通配符(?extends 上界类),固定下边界通配符(?super 下界类)

学习主要就是为了方便查看API文档

使用小细节

public  void  a(List<?> list){
// 遍历
    for (Object o : list) {
        System.out.println(o);
    }

// 数据的写入操作
// list.add("abc");--》出错,不能随意的写入

// 读取操作
    Object s  = list.get(0);
}

泛型受限

并列关系,我们如何限制类型,

  • 用extends的是本类和类所有的子类:定义上限
  • 用super是本类和本类的父类,定义下限

List<Object> a = new ArrayList<>();
        List<Person> b = new ArrayList<>();
        List<Student> c = new ArrayList<>();

A,B,C三个泛型的类型不相同,Person是Student的父类

相关文章