java 二叉树泛型_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就来弥补这个问题。

先写一下试试:

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

运行:

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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

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

需求:

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

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

Student类:

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

主函数:

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

运行:

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

发现又挂掉了:

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

这是为什么呢?

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

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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

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

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

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

点进去看看:

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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

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

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

运行:

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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

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

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

运行:

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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

为什么呢?

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

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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

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

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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

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

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

String类中有个compareTo方法:

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

运行:

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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

03-集合框架(二叉树)

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

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

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

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

下面这个例子中:

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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

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

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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

我们如果返回-1:

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

存放过程:

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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

如果返回0:

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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

|——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的第二种排序方式:                                                                                                          当元素自身不具备比较性时,或者具备的比较性不是所需要的,                                                  这时就需要让集合自身具备比较性。                                                                                              集合初始化时,就有了比较方式。

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

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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

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

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

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

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

点进去看看:

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

它的返回值:

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

运行:

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

成功了哦。

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

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

问题解决了呢。

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

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

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

所以它也有compareTo方法:

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

运行:

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

都是OK的。

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

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

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

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

比较器是什么概念呢?

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

这个规则就是Comparator。

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

05-集合框架(TreeSet练习)

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

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

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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

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

我们修改一下代码:

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

运行:

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

发现排序成功。

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

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

运行:

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

发现“aaa”没有存进去。

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

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

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

再运行:

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

OK了。

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

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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

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

接下来讲下一个知识点。

先看示例:

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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

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

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

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

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

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

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

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

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

我们看这个示例:

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

编译的时候就出错了:

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

为什么呢?

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

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

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

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

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

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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

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

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

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

为什么没有了呢?

因为安全了呀。

泛型的好处:

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

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

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

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

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

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

我们看一下Collection接口:

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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

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

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

它里面也有E。

我们再看看方法列表:

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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

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

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

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

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

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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

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

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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

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

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

编译运行:

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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

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

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

08-集合框架(泛型类)

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

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

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

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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

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

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

所以换一种定义方式:

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

这样是否就通用了呢?

试一下:

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

我们将代码修改一下:

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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

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

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

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

这就是传说中的泛型类。

主函数中:

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

编译运行都没有问题:

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

把最后一句的强转去掉:

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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

传进Student对象试一下:

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

什么时候定义泛型类?

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

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

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

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

例:

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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

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

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

这样就太麻烦了。

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

修改后的代码:

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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

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

可以的。

比如这样:

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

使用它:

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

编译会出现错误提示:

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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

特殊之处:

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

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

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

再使用它运行就成功了:

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

注意不可以写在这里哦:

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

会编译失败:

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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

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

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

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

运行,没有问题:

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

运行,也是OK的:

223d54bd3088?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值