Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口

2019/7/12  14:15二刷留念


    01-集合框架(TreeSet)

        接下来说Set集合中的TreeSet。

        |——Set:元素是无序(存入和取出的顺序不一定一致),元素不可以重复。(想重复找List,不重复找Set)

                |——HashSet:底层数据结构是哈希表。

                    HashSet是如何保证元素唯一性的呢?

                    是通过元素的两个方法,hashCode和equals来完成。

                    如果元素的HashCode值相同,才会判断equals是否为true。

                    如果元素的hashcode值不同,不会调用equals。

                |——TreeSet:可以对Set集合中的元素进行排序。

        Set集合是无序的,这点有点缺憾,于是TreeSet就来弥补这个问题。

        先写一下试试:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第1张图片

        运行:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第2张图片

        我们发现,虽然它打印的顺序和我们存的顺序不一样,但是也是有自己的固定顺序的。

    02-集合框架(TreeSet存储自定义对象)

        需求:

        往TreeSet集合中存储自定义对象学生。

        想按照学生的年龄进行排序。

        Student类:       

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第3张图片

        主函数: 

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第4张图片

        但是运行的时候发现报错了:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第5张图片

        我们试着改一下,只存入一个元素:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第6张图片

        运行:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第7张图片

        发现成功了。我们再存两个试试:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第8张图片

        发现又挂掉了:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第9张图片

        这是为什么呢?

        我们找到java.lang包里的Comparable接口。

        到这里我们就大概明白了。

        TreeSet集合可以实现排序,可是按照什么方式排,我们并没有告诉它。而这个例子中的学生类,根本不具备比较性。而我们必须要让元素具备比较性,TreeSet集合才能帮我们排序。这个时候我们找到了Comparable接口,只要实现这个接口,学生类就具备了比较性。

        这个接口中只有一个方法:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第10张图片

        点进去看看:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第11张图片

        其中指定对象就是传进来的o,而此对象是调用这个方法的this。

        让学生类实现Comparable接口,并重写compareTo方法:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第12张图片

        运行:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第13张图片

        我们再输出一下它的比较过程,看看都和谁比过:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第14张图片
Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第15张图片

        我们发现,CompareTo方法会自动被调用,底层在调用这个方法,当然这个类首先得实现Comparable接口。符合我们的规则,当然就可以调用子类实现的方法。

        排序成功了,可是还存在一个小问题,当出现同年龄而不同名的元素时:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第16张图片

        运行:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第17张图片

        我们发现,lisi08没有被存进来。

        为什么呢?

        我们看一下重写的compareTo方法,它是这么写的:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第18张图片

        当两者年龄相同时,返回0。

        再看看compareTo方法的详细信息:

        返回0意味着此对象等于指定对象,也就是说这两个对象相当于相同对象。

        这就是lisi08没有存进来的原因,程序将它们识别为相同对象了。

        我们的修改思路是,若年龄相同,则继续判断姓名是否相同。

        String类中有个compareTo方法:

        String类它本身实现了Comparable,Java中很多类都具备比较性:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第19张图片

        我们调用一下这个方法(因为都是实现了Comparable接口,所以返回的也是正数、负数或0):

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第20张图片

        运行:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第21张图片

        记住,排序时,当主要条件相同时,一定要判断一下次要条件。

    03-集合框架(二叉树)

        那么TreeSet底层的数据结构是怎样的呢?

        排序无非就是比较,元素越多,有可能互相比较的次数越多,这个时候效率就没那么高了。为了优化这个底层,TreeSet用了一个比较特殊的数据结构。

        用一个例子画了张二叉树的图,图上标的数字是取出数据的顺序:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第22张图片

        下面这个例子中:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第23张图片
Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第24张图片
Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第25张图片

        我们发现它存进和取出的顺序是一样的。

        下面画一下存取的过程,存放过程:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第26张图片

        而取出是从左向右来取,所以取出顺序为22、20、19、19。正序取出。

        我们如果返回-1:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第27张图片

        存放过程:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第28张图片

        取出顺序为19、19、20、22。倒序取出。

        如果返回0:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第29张图片

        发现里面只存进了一个元素:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第30张图片

        现在补充完整这张体系图:

        |——Set:元素是无序(存入和取出的顺序不一定一致),元素不可以重复。(想重复找List,不重复找Set)

                |——HashSet:底层数据结构是哈希表。

                        HashSet是如何保证元素唯一性的呢?

                        是通过元素的两个方法,hashCode和equals来完成。

                        如果元素的HashCode值相同,才会判断equals是否为true。

                        如果元素的hashcode值不同,不会调用equals。

                |——TreeSet:可以对Set集合中的元素进行排序。

                        底层数据结构是二叉树。

                        保证元素唯一性的依据:compareTo方法return 0。

                        TreeSet排序的第一种方式:让元素自身具备比较性。                                          元素需要实现Comparable接口,覆盖compareTo方法。                                                            这种方式也称为元素的自然顺序,或者叫做默认顺序

                        TreeSet的第二种排序方式:                                                                                                          当元素自身不具备比较性时,或者具备的比较性不是所需要的,                                                  这时就需要让集合自身具备比较性。                                                                                              集合初始化时,就有了比较方式。

    04-集合框架(实现Comparator方式排序)

        接下来讲TreeSet的第二种排序方式:

                        TreeSet的第二种排序方式:                                                                                                          当元素自身不具备比较性时,或者具备的比较性不是所需要的,                                                  这时就需要让集合自身具备比较性。                                                                                              集合初始化时,就有了比较方式。

        集合对象以初始化就有的比较方式,就要看一下构造函数了。

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第31张图片

        为了让集合自身具备比较性,就定义了比较器,将比较器对象作为参数传递给TreeSet集合的构造函数。

        我们依然在上节课代码的基础上做出修改。

        上节课是按照年龄排序,现在我们的需求变了,想按照姓名来排序。

        我们需要使用的这个构造函数要用到这个东西:

        点进去看看:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第32张图片

        发现是一个接口,这个接口有两个方法:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第33张图片

        它的返回值:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第34张图片

        下面定义一个新的类实现Comparator接口:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第35张图片

        在定义的容器的时候将这个新的类的对象作为参数传进去:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第36张图片

        运行:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第37张图片

        成功了哦。

        接下来解决姓名相同年龄不一样的情况:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第38张图片
Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第39张图片
Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第40张图片

        问题解决了呢。

        我们还有更简单的方式来写。年龄是一个整数,而整数有自己的对象:Integer。

        我们去Integer类中看一下,发现它也实现了Comparable接口:

        所以它也有compareTo方法:

        所以我们这样写就可以了:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第41张图片

        运行:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第42张图片

        都是OK的。

        有两种排序方式:让元素自身具备比较性,让容器自身具备比较性。

        当两种排序都存在时,以比较器为主。(比如上面例子中,最后就是以比较器(姓名)为序排序的)

        定义比较器:定义一个类,实现Comparator接口,覆盖compare方法。

        这两种排序方式中,比较器比较常用一些。

        比较器是什么概念呢?

        叫做你具备了比较性,我就按照你的排,如果你没有比较性/或者比较性不是所需要的,我对外提供了一个规则,你只要按照这个规则来写,我依然可以帮你排。

        这个规则就是Comparator。

        接口就是对外提供的功能扩展。

    05-集合框架(TreeSet练习)

        练习:按照字符串长度排序。

        我们先运行一下这段代码:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第43张图片
Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第44张图片

        发现它是按照自然顺序来排的。

        字符串本身具备比较性,但是它的比较方式不是所需要的,这时就只能使用比较器。

        我们修改一下代码:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第45张图片
Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第46张图片

        运行:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第47张图片

        发现排序成功。

        我们还可以让代码更简单一点,依然是上节课的那个方法:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第48张图片

        运行:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第49张图片

        发现“aaa”没有存进去。

        因为它和“cba”长度一样。

        我们继续修改代码,主要条件判断完了,要判断次要条件:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第50张图片

        再运行:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第51张图片

        OK了。 

        当然,我们也可以用匿名类的方式来完成:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第52张图片

        但是这样阅读性就差一些,所以还是用正常方式写好一点。

    06-集合框架(泛型概述)

        接下来讲下一个知识点。

        先看示例:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第53张图片
Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第54张图片

        我们集合当中会添加很多对象,比如说添加一个Integer对象:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第55张图片

        集合当中只能添加对象,是不能添加基本数据类型的,但是在1.5版本之后可以添加基本数据类型了,因为基本数据类型有一个自动装箱拆箱动作,所以我们直接这样写就行,自动把4封装成对象了,两句话意思一样,:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第56张图片

        我们试着编译运行一下,发现编译并没有问题,可是运行的时候就挂掉了:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第57张图片

        这个异常是类型转换异常,说Integer不能转换成String。

        可是编译的时候都没有发现,运行时却挂掉了。我们有没有办法让它在编译时就可以发现问题呢?

        我们分析一下问题怎么产生的:存入了不同类型的数据。

        那么,如果往里面全存成String,是不是就可以了呢?

        Java在1.5版本的时候就对这个问题进行了解决,提供了一个新技术,叫做泛型

        泛型:JDK15版本以后出现的新特性,用于解决安全问题,是一个类型安全机制。

        再复习一下新特性产生的三种原因:1,高效。2,简化书写。3,提高安全性。

        那么它如何解决安全性问题呢?

        我们这里可以借鉴数组定义的原则来完成。

        我们看这个示例:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第58张图片

        编译的时候就出错了:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第59张图片

        为什么呢?

        因为在定义数组容器的时候已经明确类型了,已经确定是int了。

        这也是数组比较安全的原因。

        而集合在定义的时候并未指定元素类型,所以存在了安全隐患。

        如果能像数组一样在集合定义时就指定类型,是不是就没有安全隐患了呢?这就是泛型的由来。

        我们现在为集合指定数据类型:

        这句话的意思是:我定义了一个容器,叫做ArrayList容器,这个容器中的元素是String类型。

        为什么使用的是尖括号<>呢?因为大括号{}已经被程序使用了,小括号()被参数使用了,方括号被[]数组使用了,就只剩尖括号<>了(;′⌒`) 

        好了,现在编译,发现失败了,问题从运行时期就转移到了编译时期:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第60张图片

        好,我们把那条错误语句去掉,然后再做一些小修改,将迭代器也指定数据类型:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第61张图片

        编译,发现错误提示没有了:

        而且,不仅错误提示没有了,之前编译会有的这两句注意事项也没有了:

        为什么没有了呢?

        因为安全了呀。

        泛型的好处:

        1,将运行时期出现的问题ClassCastException,转移到了编译时期,方便于程序员解决问题,让运行时的问题减少,提高了安全性。

        2,避免了强制转换的麻烦。

    07-集合框架(泛型使用)

        泛型格式:通过<>来定义要操作的引用数据类型。

        那么在使用Java提供的对象时,什么时候写泛型呢?

        通常在集合框架中很常见,只要见到<>就要定义泛型。

        我们看一下Collection接口:

        他就有,在这里,E是Element,即元素的意思,它并没有什么具体的含义。

        我们再看一下他的子类ArrayList:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第62张图片

        它里面也有E。

        我们再看看方法列表:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第63张图片

        比如add方法,我们明确的是什么类型的元素,那么add方法添加的就是什么类型的对象。

        其实<>就是用来接收类型的。

        当使用集合时,将集合中要存储的数据类型作为参数传递到<>中即可。(就如同我们的函数传参数一样)

        接下来写我们依然写之前写过的那个例子,想将存进集合中的字符串按长度来排序。

        我们发现Comparator接口也可以指定数据类型:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第64张图片
Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第65张图片

        它也可以加泛型,因为泛型避免了强转

        像我们之前写就需要强转:

        而现在为它指定了数据类型,就不用强转了。

        整个方法的代码就非常简单了:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第66张图片

        编译运行:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第67张图片

        执行很顺利,而且不再有安全提示了。

        我们在写HashSet集合的时候,覆盖了两个方法,一个叫做hashCode,一个叫做equals,equals中必须要写Object。因为这个equals复写了Object,Object有泛型吗?没有。所以必须得做转换,转换之前还得要判断它是不是这种类型。

        再总结一下,我们要定义一个对象需要做的事情:里面要自定义hashCode和equals方法,同时还要实现comparable接口,重写compareTo方法,让对象具备默认的比较性,这样既可以存到HashSet当中,又可以存到TreeSet当中。(不一定存储到哪个里面去,所以这些基本的特性都要具备)

    08-集合框架(泛型类)

        接下来有一个问题,我们能不能在定义的类中使用泛型的概念,来完成程序的设计呢?

        换句话说,Java能定义出一堆泛型类,我们能不能定义出呢?

        接下来体现一下泛型出现前后的代码。

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第68张图片

        这里有一个对应Worker类的工具类,接下来我们想定义一个Student类,也要给它定义一个工具类。那么,每个类都对应一个工具类,是不是太麻烦了呢?

        如果只是为了设置对象和获取对象,对象类型不确定,都是后面有的。

        这时,我们是不是可以提高一下程序的扩展性,抽取这些对象的共性类型。

        所以换一种定义方式:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第69张图片

        这样是否就通用了呢?

        试一下:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第70张图片

        编译运行发现都没有问题:

        我们将代码修改一下:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第71张图片

        这时再运行就出现了类型转换异常的问题: 

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第72张图片

        其实,我们这里所写的Tool类,以前程序设计的时候都用这样的方式来完成程序的扩展,比如最常见的之一equals,它就是Object类型的。

        这就是早期的代码,程序员只能自己弄清楚到底是什么类型,不能用什么类型,是很手工的方法。

        接下来是泛型出现后的代码: 

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第73张图片

        这就是传说中的泛型类。

        主函数中:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第74张图片

        编译运行都没有问题:

        把最后一句的强转去掉:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第75张图片

        发现编译运行也是OK的。(图略)

        传进Student对象试一下:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第76张图片

        编译时就会报错,直接让问题发生在了编译时期:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第77张图片

        什么时候定义泛型类?

        当类中要操作的引用数据类型不确定的时候,早期定义Object来完成扩展,现在定义泛型来完成扩展。

        注意:这里是引用数据类型哦,基本数据类型定义不了。

    09-集合框架(泛型方法)

        泛型除了可以定义在类中,也可以定义在方法中。

        例:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第78张图片

        给类定义泛型后,为我们提供了很大方便,可是也出现了局限性,那就是对象一旦建立,类型就确定了。比如在这个例子中,只能打印固定类型的数据。

        泛型类定义的泛型,在整个类中有效,如果被方法使用,那么泛型类的对象明确要操作的具体类型后,所有要操作的类型就已经固定了。为了让不同方法可以操作不同类型,而且类型还不确定,那么可以将泛型定义在方法上。

        那我们需要建立多个对象,指定不同的数据类型。

        这样就太麻烦了。

        如果我们想实现的是,建立一个对象后,可以通过这一个对象打印多种类型数据。

        修改后的代码:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第79张图片

        不同类型的元素就打印出来了:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第80张图片
Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第81张图片

    10-集合框架(静态方法泛型)

        那我们可以在泛型类中定义泛型方法吗?

        可以的。

        比如这样:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第82张图片

        使用它:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第83张图片
Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第84张图片

        现在我们定义了一个静态方法:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第85张图片

        编译会出现错误提示:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第86张图片

        因为静态方法在对象没有建立的时候就存在了,而元素类型T只有在对象建立之后才会指定,所以出现问题了。

        特殊之处:

        静态方法不可以访问类上定义的泛型,如果静态方法操作的引用数据类型不确定,可以将泛型定义在方法上。

        OK,我们修改一下这个静态方法:

        再使用它运行就成功了:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第87张图片
Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第88张图片

        注意不可以写在这里哦:

        会编译失败:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第89张图片

        这叫书写格式错误,泛型定义在方法上时,永远要放在返回值类型的前面,修饰符的后面。

    11-集合框架(泛型接口)

        泛型定义在接口Inter上,InterImpl类在实现这个接口的时候指定了数据类型:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第90张图片

        运行,没有问题:

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第91张图片

        接下来是另一种情况,InterImpl类在实现这个接口的时候也不知道该操作什么数据类型(这种用法其实不多见):

Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口_第92张图片

        运行,也是OK的:

你可能感兴趣的:(Java基础day15笔记:TreeSet|二叉树|实现Comparator方式排序|泛型|泛型类|泛型方法|静态方法泛型|泛型接口)