java学习笔记18

来源:互联网 发布:淘宝如何改会员名 编辑:程序博客网 时间:2024/05/24 07:24

1、集合框架的构成


凡是remove都改变长度。

2、map有其独特的类型写法map<key,value>一个键key对应一个值value,主要强调的是对应关系,键key可以是一个类型的对象,值value也可以是一个类型的对象,map的用途主要是强调这两个类型之间有对应关系。


hashmap由于是hash,所以也是无序的。Collection集合中有迭代器,Map是另一种集合,与Collection没有关系,所以内部并没有迭代器。key可以理解为丈夫,value可以理解为妻子。remove(key)返回的是这个key对应的值,若果没有这个key,那自然也没有对应的值value,所以返回的是null。key值一旦相同新的value值就会覆盖原有的value,key值不同时,value值相同也没有关系。产生的还是新的键值对。



还有第二种获得Map中元素的方法:通过entrySet(结婚证),结婚证上有丈夫(key)和妻子(value),这样通过结婚证自带的方法很容易就可以得到key和value。


在内存空间的实质就是把key 和value封装成一个entry结婚证对象存在entrySet中


4、Map.Entry是接口Map的静态内部接口,因为Map.Entr存的是Map中成员key和value之间的关系(结婚证书),那么必然是先有Map的成员key和value,才有结婚证书。所以Map.Entry是接口Map的静态内部接口随着Map的加载而加载,Map.Entry是Map的嵌套内部接口,外部规则里面有内部规则,内部规则直接访问外部规则的内 容


迭代器的写法要保持迭代器所属的集合的写法一致,如下图中都带<String>:Collection<String> ,对应的Interator<String>


Set在底层其实就是用Map实现的,要Set就是为了和List相对应,保证元素对象的唯一性。


之前讲过hash的比较方法,先比较hashCode()是否相同,再比较其内部内容是否相同。而刚开始我们的Student类没有覆盖hashCode和比较内容equals方法,所以比较的是对象的引用地址值,自然不同,全部都存进了,后面把这两个方法全都覆盖重写了,对象名字一样的自然就是一样的key,既然是一样的key,就存不进去HashMap 中了。

下图是利用TreeMap实现有特定顺序的存入元素对象。



integer的自动装箱拆箱是java为了简化书写 ,而泛型是java为了解决安全问题的新特性。


ArrayList<E>,尖括号里面的E就是个类型参数相当于Object,E可以理解为Element的缩写,那么E为什么要大写呢?因为ArrayList接收的都是引用数据类型(对象),要么是类,要么是接口。而类或者接口都必须首字母大写,所以E也就大写了。

没有泛型之前,这些集合都是接收Object,所以传进来的元素对象相当于向上转型了,但是在用迭代器的输出的时候如果想要用传入元素对象特有的方法就又必须向下转型,也即类型强转。本来是集合要传入同一种数据类型的对象,这样方便在后面迭代操作时不出错,如果在传入的时候不小心传入了别的数据类型的对象,那么编译不会错,但是在运行的时候由于要强转类型(例如Integer转为String)会报错。引入泛型<>之后,相当于定义了集合容器存入的数据类型,如果传进来的对象的数据类型不满足的话,就在编译时直接报错了,避免了安全隐患。由于泛型已经确定了容器传入对象的数据类型(也就相当于规定了容器只能存特定数据类型的对象),所以后面迭代器也已经确定了类型,迭代出来的对象的类型也必然就确定了,所以it.next()就可以直接用了,而不需要在其前面再加强转符号。


泛型技术提高了编译的安全性,有问题的在编译时就暴露出来了,直接在编译就不通过。

 2、泛型只是在编译时有的,在运行时会去掉泛型,因为泛型是1.5的新特点,而1.5的java虚拟机的类加载器是1.4的老版本(不支持泛型),所以为了兼容,在运行时是去掉了泛型的。运行时去掉泛型(去掉了传入对象数据类型的限制),(给你一个集合,只是说传进来的所有元素对象的数据类型必须一致,你可以都传String,都传Person类型等,所以没有泛型限定的话就是啥都可以接收)那么运行时默认接收的是Object类型,而在迭代器取元素对象的时候还是会有强制类型的问题,这就涉及了java的泛型补偿机制,它会自动帮忙强制类型转换。


Alt+shift+s出现创建方法(覆盖方法)的快捷键

4、泛型类

一个类的设为泛型参数<q>,这样在实际运用时再指定传入的类型。相当于定义的时候任何类型都可以接受,相当于接受Object,但是在运用是指定了特定的存储类型,就只能存那个类型的对象了。

指定什么类型,就操作什么类型的对象。

5、定义在方法上的泛型

如果将泛型定义在类上,而且里面的方法也跟着定为和类一样的泛型,那一旦在运用时传入了特定的类,那就只能用那个类型的对象了。包括里面的方法,但是我们还可以在定义了泛型的类中,再将其中的方法定义为另外的泛型(相当于里面的方法适用于Object对象),这样,类可以指定一个数据类型后,方法继续使用于别的类型对象。




<W>只是个声明W是泛型,要放在修饰符后面,返回值前面的位置。作用其实和(Object str)效果一样,Object无非在函数里面还需要类型强转。静态方法因为不需要对象就可以用,而没有对象就没有指定类型也就只能用<w>这种方法。




QQ就相当于是将泛型定义在了类上。

6、泛型还可以定义在接口上 


7、使用通配符<?>效果和<T>的差不多。下面的应该是(Collection<?> al) ,it.next()返回的类型不确定,不能直接赋给?类型对象

(Collection<Person>)在用的时候,容器就只能传Person类对象,(定义时定义为Person,而在main函数中运用时若定义只能传Student也是会报错的)若<Student>就只能传Student对象。但是如果用?就又啥都能传,也不太好。如果只想传Person及子类Worker和Student,那就必须写成<? extends Person>的形式,注意也可以传Person对象进来!

8、限定了Person,但是Person及其子类都可以传进来,下面子类可以随便变,所以就是上限。同理还可以限定下限。



10、什么时候使用<? super Student>

加入我们在容器中加入了Person对象,又在其中加入了Student对象,Person类之前有覆盖重写过的自己的按名字比较(名字一样再按年龄)的方法,比较方法接收的对象是两个Person,同样Student类里面也有覆盖重写过的自己的按名字比较(名字一样再按年龄)的方法,比较方法的具体内容都是一样的,但是比较方法接收的对象是两个Student,但是很明显Person和Student的比较方法是一样相通的。所以可以指定一个公共的比较器,可以把Person类对象和Student类对象放在一起,按照统一的规则来比较大小,就是的CompByName比较器(都用的是Person的比较器),Student是Person的子类,那么比较对象的接收都用Person来接收,这样就可以实现两类对象在一起比较。

java中快速导入包Ctrl+Shift+M




两个不同类型的对象Person和Student 作比较,用的都是Person的比较器,Student对象传进来,Person o1也刚好能接收,所以可以用公共的比较器。



上图的意思就是Student类用了Person类的比较器。

11|、下图中ContainAll(Collection<?> coll)之所以用Collection<?>是因为containAll方法里面的实质是用equals方法来判断,而每个对象都继承自Object,都有equals方法,所以所有对象都可以传进来,所以可以打上?表示传进来对象的类型不确定。同理,任何对象都有toString()方法。你确定要传入String,Person等类型是可以用<E>,你只传Person时可以用<Person>,当你完全不知道要传什么的时候就用<?>


12、总结如下


0 0
原创粉丝点击