泛型1(Java)

1.泛型的定义

1.1 什么是泛型?

泛型就是让一个类/一个方法,能够支持多种不同的数据类型。

1.2 为什么要使用泛型?

public class MyArray {
    private int [] arr=null;
    private int size;
    private int capacity;

    public MyArray(int capacity){
        arr=new int[capacity];
        size=0;
        this.capacity=capacity;
    }

    public void add(int index,int data){
        if(size<capacity){
            arr[size++]=data;
        }
    }

    public int get(int index){
        return arr[index];
    }

    public int size(){
        return size;
    }

    public static void main(String[] args) {
        //创建一个MyArray对象,里面存储的是int类型的数据
        MyArray m1=new MyArray(10);
        m1.add(0,1);
        m1.add(1,2);
        m1.add(2,3);

        for(int i = 0;i<m1.size();++i){
            System.out.print(m1.get(i)+" ");
        }
        System.out.println();
    }
}
  • 如果没有泛型机制,当前封装的数组类,只能针对int进行,如果需要针对String ,就需要在创建一个类,把里面的int的类型改成String,后续如果需要新增其他的类型,就得如法炮制。
  • 有了泛型之后,就可以一套代码可以服务于多种类型
  • 在上面的方式中,将存储数据的类型全部有int类型改成Object,因为Java中的Object是所有类的基类
  • 如果把类中持有的数组写成Object[],此时是可以用来存储多种不同类型数据的。但是这样写,就得写大量的”类型转换“相关的代码。
public class MyArray {
    public Object[] data = null;
    private int size = 0;
    private int capacity = 10;

    public MyArray(){
        data=new Object[capacity];
    }

    public void add(Object data){
        if(size >= capacity){
            return;
        }
        this.data[size++]=data;
    }

    public Object get(int index){
        return data[index];
    }

    public static void main(String[] args) {
        MyArray myArray=new MyArray();
        myArray.add(new Person("张三",18));
        myArray.add(new Person("李四",19));
        myArray.add(new Person("王五",20));

        Person person=(Person)myArray.get(0);
        
        MyArray myArray2=new MyArray();
        myArray2.add(new String("aaa"));
        myArray2.add(new String("bbb"));
        myArray2.add(new String("ccc"));
        
        String str=(String)myArray2.get(0);
        
        MyArray myArray3=new MyArray();
        myArray3.add(new Integer(1));
        Integer integer=(Integer)myArray3.get(0);
    }
}

  • 使用Object来凑合完成”泛型“效果,是比较麻烦的
  • 1.需要写一些类型转换的代码
  • 2.类型转换的代码容易出错,缺少一些必要的类型检查。

2.泛型类

2.1泛型类的定义

class 泛型类的名称<类型形参列表>{
	//这里可以使用类型参数
}

class ClassName<T1,T2,...,Tn>{
	//类实现体
}

类型形参一般使用一个大写字母表示,常用的名称有:

  • E表示Element
  • K表示Key
  • V表示Value
  • N表示Number
  • T表示Type
  • S,U,V等等

2.2泛型类的例子

//泛型版本,实现刚才的数组封装类
//类名后面就需要加上<E>,<>表示当前这个类是泛型类
//E相当于是一个形参,E表示某一中具体的类型
//会在实例化的时候确定E具体是哪种类型
public class MyArray2<E>{
    //创建的数组,类型不是Object,而是直接使用E作为类型
    //后续在实例化这个MyArray2时,确定了E是啥类型,也就知道了data最后的类型
    private E[] data=null;
    private int size=0;
    private int capacity=10;

    public MyArray2(){
      //由于E这样的类型是不确定的,无法直接创建E类型的实例
        data=(E[])new Object[capacity];

    }

    public void add(E data){
        if(size >= capacity){
            return;
        }
        this.data[size++] = data;
    }

    public E get(int index){
        return this.data[index];
    }
}
  • 使用泛型的时候,在争对对象实例化的时候需要填入泛型参数的实际类型。
  • 把这个实际参数填写进去之后,实际的泛型参数就被自动的替换成了String
  • Java的泛型只能是引用类型,如果是内置类型,就需要对应的包装类
  • Java的泛型,还是基于Object实现的,本质上还是Object[],就是帮助我们完成了类型校验和类型转换。

2.3泛型类的实例化

2.3.1实例化语法

泛型类<类型实参>变量名 :定义一个泛型类的引用。
new 泛型类<类型实参>(构造方法实参): 实例化一个泛型类的对象

2.3.2实例化的例子

public static void main(String[] args) {
        //后面的尖括号中的内容可以省略
        //因为前后泛型的参数必须是一致的
        MyArray2<String> myArray2=new MyArray2<String>();
        myArray2.add("hello");
        myArray2.add("world");
        
        //此时进行获取元素的时候,就不需要类型转换了
        String str=myArray2.get(0);
        MyArray2<Integer> myArray3=new MyArray2<>();
        myArray3.add(10);
        myArray3.add(20);
//        myArray3.add("hello");

        Integer ret=myArray3.get(0);
    }

注意:

  • 1.右侧<>中的类型可以省略
MyArray2<Integer> myArray3=new MyArray2<>();
  • 在new MyArray2<>()对象时,<>中未明确指明类型,编译器会根据=左侧中<>的类型来推演。
  • 2.左侧<>中的类型不能省略
MyArray2<> myArray3=new MyArray2<String>();//省略之后,编译失败
  • 编译器在推演时,是根据左侧类型来推演右侧的
  • 3.虽然右侧的<>可以不用写类型,但是<>不能省略
MyArray2<String> myArray3=new MyArray2();
  • 上述代码会产生警告

2.4泛型类的定义-类型边界

  • 类型边界:定义泛型类的时候,对未来实例化的时候传入的参数实参做出限制。
  • 泛型参数这里的类型不应该随便填,要根据实际情况做出约束
public class MyArray2<E extends Animal>{
    //创建的数组,类型不是Object,而是直接使用E作为类型
    //后续在实例化这个MyArray2时,确定了E是啥类型,也就知道了data最后的类型
    private E[] data=null;
    private int size=0;
    private int capacity=10;

    public MyArray2(){
      //由于E这样的类型是不确定的,无法直接创建E类型的实例
        data=(E[])new Object[capacity];

    }

    public void add(E data){
        if(size >= capacity){
            return;
        }
        this.data[size++] = data;
    }

    public E get(int index){
        return this.data[index];
    }

    public static void main(String[] args) {
        //后面的尖括号中的内容可以省略
        //因为前后泛型的参数必须是一致的
        MyArray2<Bird> myArray4=new MyArray2<>();//编译成功,因为Bird是Animal的子类
        MyArray2<String> myArray2=new MyArray2<>();//编译失败,因为String不是Animal的子类
        myArray2.add("hello");
        myArray2.add("world");
        }
    }

注意: 没有指定的类型的边界E,可以视为E extends Object

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值