泛型 -- 基本原理推导(不用再死记硬背)

泛型是什么?

泛型是什么呢?从字面意思来理解就是广泛的类型(个人理解)。泛型是 jdk1.5 的产物,被业界大佬称之为 jdk 的里程碑事件。到底是什么原因使得这样的产物让广大 Java 程序员赞不绝口。听我细细侃来。

引出泛型:

每件事物的产生必然有一定的道理,泛型亦是如此。
我们来看一下下面这个集合:

public class Ttest01 {

    public static void main(String[] args) {

        MySet set = new MySet();

		// 向集合中添加一个字符串
        set.add("abc");

        String info = (String) set.get(0);
        System.out.println(info);
	
		// 向集合中添加一个整数
        set.add(2);
		// 插入一个整数,取的时候除了我们自己没有人知道插入的类型是什么
		// 究竟强转成什么,不同的用户有不同的选择
        String info1 = (String) set.get(1);
        System.out.println(info1);
    }
}

// 集合类
class MySet{

    Object[] mySet = new Object[10];
    int idx = 0;
    // 向集合中插入一个元素
    public void add(Object value) {
        mySet[idx ++] = value;
    }

	// 获取元素的值
    public Object get(int idx) {
        return mySet[idx];
    }
}

通过上面的样例,代码在编写的过程中是不会报错的,但是在实际运行过程中呢?
在这里插入图片描述
显然代码报错了。
先不说代码有错的问题,假设给你一个这样的集合,咱不知道集合中每个元素的数据类型,咱是不是要一个一个进行强制转换呢?而且我们也不知道究竟应该转成哪种类型才不会报错。(我要是项目经理,估计就被气死了)

泛型应运而生:

既然一个集合中有String类型,有 Integer 类型,那么我们能不能一个集合中只存储 String ,一个集合只存 Integer 类型呢?显然是可以的。
看代码:

public class Ttest01 {

    public static void main(String[] args) {

        MySet1 set = new MySet1();

        set.add("abc");

        String info = (String) set.get(0);

        System.out.println(info);
    }
}


class MySet1{
    String[] mySet = new String[10];
    int idx = 0;
    public void add(String value) {
        mySet[idx ++] = value;
    }

    public String get(int idx) {
        return mySet[idx];
    }
}

当我们规定这个集合中只能存 String 类型时,那么我们想插入一个 Integer 类型的数据时会出现什么情况呢?
在这里插入图片描述
红线警告了,说明我们只能向集合中插入 String 类型。

当指定集合中的具体类型有什么好处呢?
1、给予每个使用该集合的用户 明确的信息。
2、如果插入不同的数据类型会进行错误提示。
3、不再需要进行不确定的强制类型转换

可能有的小伙伴会想,我们原来的集合既可以存储String类型的,又可以存储 Integer 类型的,这样不好吗?
别慌,相信现在你已经明白一点,原来的方式取出时是不方便的,并且对于一个不知道你的集合中各个元素的数据类型的用户来说,使用起来是及其不方便的
还有一点,在后面会提到。

泛型推导:

说了这么多废话,终于到Boss出场了。
当我们想让一个集合中都是 Integer 类型会怎么做呢?

class MySet2{
    Integer[] mySet = new Integer[10];
    int idx = 0;
    public void add(Integer value) {
        mySet[idx ++] = value;
    }

    public Integer get(int idx) {
        return mySet[idx];
    }
}

我们上面的 String 类型是什么样的呢?

class MySet1{
    String[] mySet = new String[10];
    int idx = 0;
    public void add(String value) {
        mySet[idx ++] = value;
    }

    public Object get(int idx) {
        return mySet[idx];
    }
}

仔细观察一下就会发现,这两个类型里面有很多重复的代码,如果说 之后还会有 Double,Person、Dog 类型的,我们是不是要写更多的代码呢?了解 Java 的都
多少知道一点,就是代码的复用

class MySet1{
    X[] mySet = new X[10];
    int idx = 0;
    public void add(X value) {
        mySet[idx ++] = value;
    }

    public X get(int idx) {
        return mySet[idx];
    }
}

看这个代码,我们将两份代码中不同的部分用 X 替换掉,每次只调用这个是不是就 OK 了。

那么如何传递这个 X 呢?

class MySet1<X>{
    X[] mySet = new X[10];
    int idx = 0;
    public void add(X value) {
        mySet[idx ++] = value;
    }

    public X get(int idx) {
        return mySet[idx];
    }
}

上面的方式是不健全的,说白了就是有问题的,在泛型类中是不可以直接 new X[10] 的,具体就不再详细说了(原谅博主的尴尬,下面的例子效果是一样的,具体看下面的例子吧)。
所以不得不通过另一个例子来说明问题了,实际上只要知道 X 是怎么推出来的就行了

通过下面的例子我们看一下如何调用:

import org.omg.CORBA.Object;

import java.util.Arrays;

public class Ttest01 {

    public static void main(String[] args) {

        MySet1<String> set = new MySet1<String>();

        set.add("a");

        System.out.println(set.get());


    }
}

// 给予类一个放参数的位置
class MySet1<E>{
    private E value;
    public void add(E value) {
        this.value = value;
    }
    public E get() {
        return value;
    }
}

像方法一样 加个参数就可以啦。

想让集合中都是 Integer 类型怎么办呢?

      MySet1<Integer> set = new MySet1<Integer>();

所以根据需要修改不同的参数即可。

如果想集合中既有String又有Interger 呢?

	MySet1 set = new MySet1();

看下完整代码:

import org.omg.CORBA.Object;

import java.util.Arrays;

public class Ttest01 {

    public static void main(String[] args) {

        MySet1 set = new MySet1();

        set.add("a");
        set.add("123");

        System.out.println(set.get());


    }
}


class MySet1<E>{
    private E value;
    public void add(E value) {
        this.value = value;
    }
    public E get() {
        return value;
    }
}

是没问题的,运行结果也是没问题的,可以自己尝试一下。
所以说,泛型是原先集合的加强,在原来的基础上进去强化。

类是对象的模板,泛型是类的模板

这句话通过上面的例子可以好好琢磨一下,根据泛型我们可以创建的不同的类,
MySet1< Integer >
MySet1< String >
仔细看看确实蛮有道理的,嘻嘻。

泛型好在哪里?

下面是我从某个地方的论坛上看到的,感谢大佬,引用一下:

Java语言引入泛型的好处是安全简单。泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,提高代码的重用率。

1,类型安全。 泛型的主要目标是提高 Java
程序的类型安全。通过知道使用泛型定义的变量的类型限制,编译器可以在一个高得多的程度上验证类型假设。没有泛型,这些假设就只存在于程序员的头脑中(或者如果幸运的话,还存在于代码注释中)。

2,消除强制类型转换。 泛型的一个附带好处是,消除源代码中的许多强制类型转换。这使得代码更加可读,并且减少了出错机会。

3,潜在的性能收益。
泛型为较大的优化带来可能。在泛型的初始实现中,编译器将强制类型转换(没有泛型的话,程序员会指定这些强制类型转换)插入生成的字节码中。但是更多类型信息可用于编译器这一事实,为未来版本的
JVM 的优化带来可能。由于泛型的实现方式,支持泛型(几乎)不需要 JVM
或类文件更改。所有工作都在编译器中完成,编译器生成类似于没有泛型(和强制类型转换)时所写的代码,只是更能确保类型安全而已。

后记:

基本就介绍完了,中间有点小尴尬,不过相信正在看的你一定可以理解的,如果有疑问的可以随时问我,相互学习,共同进步。
如果感觉对您有帮助,点个赞,点个关注哦,感谢感谢。
加油!少年!

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

潘小蓝

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值