数据结构-泛型

🌸🌸🌸今天主要来认识泛型~

🌸🌸什么是泛型呢?

🌸泛型是从什么时候有的呢?

首先,泛型并不是从Java的开始就存在的,而是在Java1.5版本中引入的。

接下来我们来具体看一下泛型是什么。我们以冒泡排序为例,在对数据进行排序时,数据类型是不同的,有double[ ] sort、int[ ] sort等等......如果对每种数据类型都写相应的算法,可以实现但是工程量太大。

因此,引入了泛型。

泛型不讨论基本数据类型,只讨论引用数据类型(对象)。

引用是有上下级关系的,比如:

class A extends B{...} 我们就可以认为B是A的上级

class A extends C{...} 我们就可以认为C是A的上级

如果b=a;那么b类型是a类型的上级

如果c=a;那么c类型是a类型的上级 //向上转型是自然的

Java中的Object类,是顶级类型,是所有类型的上级。

Object o=一切引用;

在没有泛型之前,Java解决多种不同类型的冒泡排序问题是通过Object来解决的(只针对引用类型)。

但是使用Object是存在一些矛盾的。比如:

//编写代码的人希望数组中放的是Student对象
Object o={....};
o1=Student 对象;//符合预期,并且代码没有语法错误
//其他编写代码的人不知道这个规则
o2=Teacher 对象;//不符合预期,但是代码没有语法错误

由此可见,使用Object无法从语法层面将不符合预期的赋值在初期暴露出来。

因此,再次强调引入泛型的必要性。

泛型(Generic Type)把类型变量化。底层原理是引用的向上转型是自然的。
基本数据类型是无法使用泛型的(将基本类型一一对应一个包装类型来解决的)。

关于泛型我们需要掌握以下几点:

1.实现带有泛型能力的方法(泛型方法的定义);

2.泛型方法的使用;

3.定义一个带有泛型的类/接口

4.🌸泛型类/接口的使用

5.泛型的特殊规则

1.泛型方法的定义

//返回值类型前面的<E>:定义了一个类 类型变量E
public static <E> void sort(E[] array){
}

2.泛型方法的使用

//泛型方法的使用
public static void test(){
    Random[] array =new Random[10];
    //标准写法
    BubbleSort.<Random>sort(array);//指定了变化的数组类型时Random
    //省略写法
    BubbleSort.sort(array);
}

3.定义一个泛型类

//定义泛型方法(接口同理)
public class GenericClass<T1,T2,T3>{
    T1 a;
    T2 b;
    T3 c;
}

在新建对象的时候才创建T1,T2,T3的类型。

4.🌸泛型类/接口的使用

public class UseGenericClass {
    public static void main(String[] args) {
        //Random,String,Scanner
        //完整写法
        //引用上通过<>体现类型
        //new对象时,类名后面要体现类型
        GenericClass<Random,String, Scanner> r;
        r=new GenericClass<Random,String,Scanner>();
        
        GenericClass<Random,String, Scanner> s=new GenericClass<Random,String,Scanner>();
        //常见写法
        //new的时候类型可以省略但是<>不能省略
        GenericClass<Random,String, Scanner> t=new GenericClass<>();
    }
}

5.泛型的特殊规则

在源码中有泛型->经过编译器编译->字节码文件(类文件)(泛型消失)->虚拟机

以上过程就是泛型的擦除

a.擦除的时候,擦到类型的上限:

class GenericClass<T extends A>{
    //T的上限是A
    T t;//编译完成后,是A t;
}
new GenericClass<A>();
new GenericClass<B>();//B是A的下级(B是A的子类,B是A的实现类)
new GenericClass<C>();//C和A没有关系,或者C是A的上级,则无法通过

class GenericClass<t>等价于 GenericClass<T extends Object>();

擦除成它的上限

b.使用时可以使用通配符

void func(GenericClass<?> c){

}

?表示可以填充任意值。

小结

完整的尖括号是泛型的标志。

对lambda表达式:

interface A{
    void func(String s);
}
void tset(A a){...}
//标准写法
class B implements A{...}

B b=new B();
test(b);
//尤其是只用一次的情况下。以上写法太啰嗦

//因此,引入匿名对象(适合只用一次的对象)
test(new A(){...}); //定义一个A的子类没有名字,同时实例化一个对象

//如果接口中只有一个方法(或者只有一个方法需要重写),可以使用lambda表达式
test((String x)->{...});
(String x)->{...}//->是lambda 表达式的标志
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值