美文网首页
Java基础day15笔记:泛型限定

Java基础day15笔记:泛型限定

作者: 楠楠喜欢泡枸杞 | 来源:发表于2018-12-27 23:18 被阅读0次

    12-集合框架(泛型限定)

        接下来说一说泛型的高级应用。

        例子:

        将al传进printColl中打印:

        将al1传入printColl打印:

        发现挂掉了:

        必须挂的,因为左右两边类型不匹配:

        可是我们又需要打印Integer类型的数据,难道要再写一个方法吗?好麻烦呢。

        那有没有办法打印任意类型的数据呢?

        有这样一种方法:当我们的对象类型不确定时,我们可以通过一个通配符来表示:

        虽然也可以这样写(比如早期没出现泛型的时候都是这样写):

        这样写即使传入使用泛型的对象也是可以的,但是这样写不够严谨,我们还是在这里写一个占位符更严谨。

        现在我们再试一下:

        全部都顺利打出来了:

        也可以不用<?>用,但是方法名前面一定也要写上哦:

        那<?>和有什么区别吗?

        有的,不过不是很大。

        是一个具体类型的话,就可以接收并操作这个类型,比如这样:

        但是如果写成<?>,就无法进行这个操作。

        代表一个具体类型,传什么类型就是什么类型,而?是不明确类型,叫做占位符,告诉你我这里有泛型,但是泛型是什么不知道。

        不明确具体类型的情况下用<?>表示。

        我们这里依然用<?>来表示,现在有一个问题,我们是否可以直接打印长度?

        不可以。

        为什么呢?

        因为代表不明确类型,而.length()是一个具体类型的方法。如果传Integer,它就没有这个方法。

        所以用泛型有好处,可以提高扩展性,但是它不可以使用类型特有方法。

        但是toString()方法就可以,因为所有类型都具备这个方法:

        总之,类型调用方法这里我们要注意一下。就像多态,提高了扩展性,但是也有弊端:不能预先使用子类中的特有方法。

        新的例子:

        Person类:

        定义一个容器al,存入Person对象:

        运行,一切正常:

        现在来了一个学生类,它继承了Person类:

        然后我们继续定义一个新的容器并存入Student:

        编译:

        失败了。

        主函数中最后一句代码:

        printColl(al1);

        就相当于:

        ArrayList al=new ArrayList();

        这个是不允许的。

        为什么不允许呢?Student不是Person的子类吗?

        拿动物和猪(猪是动物的子类)打个比方吧:

        ArrayLis<动物> al=new ArrayList<猪>();

        我们定义的是要存动物(等号左边),而真正的窝里面存的是猪(等号右边)。我们考虑到了定义的集合是可以存储动物的(等号左边),于是找了条狗想要存进去,可是窝里面只能装猪(等号右边),狗进去之后类型就冲突了,再往出取的时候就很容易出现类型安全问题。(还是不太懂,之前讲多态的时候,这样不是都没有问题吗?而且我理解的是这次存的是猪,下次存的是狗,并不是一次存入不同的,感觉也不矛盾?

        道理其实很简单,把狗扔到猪圈里,猪就疯了。

        那如果这样写呢:        

        ArrayList al=new ArrayList();

        这样也不行。

        总之,左右两边一定要一致。

        那我们这样写是不是就可以了:

        这样既可以接收Person对象,也可以接收Student对象。

        但是这样一来,除了Person和Student对象,其他的什么类型的对象也都可以进来了。而我们现在就只想用这个方法来打印Person和Person的子类,其他类我们不想受理。

        这个时候就来了泛型限定:

        它表示可以接收Person类型和Person的子类类型。

        运行:

        OK了。

        这就是我们所说的泛型限定,而泛型限定分为两种:上限和下限。

         总结一下:

        ?:通配符,也可以理解为占位符。

        ? extends E:可以接收E类型或者E的子类型。这是上限。

        ? super E:可以接收E类型或者E的附类型。这是下限。

        什么时候用到下限呢,我们在TreeSet的构造方法中发现了:

        这是什么意思呢?

        举个例子:

        也可以这样写:

        Person可以接收Student吗?

        可以。

        我们如果比较this.getName()的话,Person也具备这个方法:

        比较器:

        我们再返回看一下构造函数:

        那写Person也可以:

        这样写之后,我们依然可以接收Student对象:

        所以不管是传Student类型还是Person类型都可以,它们都可以接收Student对象。

        这就是下限的例子。

        在这个方法中,既可以接收Person也可以接收Person的子类型,限定了上限:

        而比较的时候,我们限定了下限,既能比较Student,也能比较Person:

        我们可以在TreeSet中看到几个方法:

        这个的意思是,往里面添加的时候,只要是E或者E的子类型,都可以操作E,多态嘛。

        而这个也是一样,比较的时候,比较的类型、或者比较的父类型,都能够接收子类对象进来。

        这里还有个的例子:

        这个方法上并没有定义泛型,而是用<?>来表示占位符。而泛型定义在类上了:

        上面的意思是,我要比较另一个集合的时候,这个集合不确定,传进去什么集合就是什么集合。不写<?>也可以,但是在1.5版本以后,Colletion后面都带着<>,所以还是写个占位符放在里面,类型不明确的情况下,用?来表示就可以了。

    13-集合框架(泛型限定2)

        再一个例子。

        Person类和它的子类Student类:

        但是这样打印是没有意义的,因为学生对象不具备比较性。

        我们现在要写一个比较器:

        再看一下TreeSet接口,它传入的是:

        构造方法中,可以接收E类型和E的父类型:

        所以比较器写是对的。

        继续:

        将比较器传进去:

        运行:

        OK了。

        接下来Worker类继承了Person类:

        新写了一个Worker比较器:

         主函数中存入Worker对象并打印: 

        运行也是没有问题的:

        但是好麻烦,每次搞一个对象都要搞一个比较器。

        我们可以直接在比较其中写它们的父类型(因为构造函数中可以接收E及E的父类型):

        它的子类们直接使用这一个比较器就可以了:

        运行都是OK的,图略。

        但是有一点要注意,比较器中使用的只能是父类的方法。有扩展性就有局限性。

相关文章

  • Java基础day15笔记:泛型限定

    12-集合框架(泛型限定) 接下来说一说泛型的高级应用。 例子: 将al传进printColl中打印: 将al1传...

  • java基础

    八、泛型 面试题==什么是泛型中的限定通配符和非限定通配符 ?这是另一个非常流行的Java泛型面试题。限定通配符对...

  • java泛型

    1:问:什么是 Java 泛型中的限定通配符和非限定通配符?有什么区别? 答:限定通配符对类型进行限制,泛型中有两...

  • 泛型、型变与投影

    简单泛型 kotlin 对于简单泛型的支持与java类似, 可以通过通配符,提升代码的灵活度 限定型泛型 在编码实...

  • 九、泛型

    九、泛型 尽量不要写这种有能与泛型方法重载的代码,有迷惑性 限定传入 T 的类型 泛型数组 Java 不支持泛型类...

  • 《Java编程思想 Generics》读书笔记一——泛型的基础知

    该学习笔记只记录了《Java编程思想 泛型》一章前面部分的基础知识,这里没有跟泛型无关的的知识。 不使用泛型怎么写...

  • Java 泛型

    导读 移动开发知识体系总章(Java基础、Android、Flutter) 为什么会有泛型? 泛型类 泛型方法 泛...

  • Java泛型转换

    Java泛型转换的事实 虚拟机中没有泛型,只要普通的类和方法 所有类型参数都用他们的限定类型替换。无限定类型的用O...

  • JAVA泛型•通配符限定

    为了更好地阅读体验,欢迎访问博客原文 引一个例子 考虑一个这样的场景,计算数组中的最大元素。 仔细看看code01...

  • Java泛型教程

    Java泛型教程导航 Java 泛型概述 Java泛型环境设置 Java泛型通用类 Java泛型类型参数命名约定 ...

网友评论

      本文标题:Java基础day15笔记:泛型限定

      本文链接:https://www.haomeiwen.com/subject/xadjlqtx.html