,一.
回过来说一下ArrayList,现在用ArrayList对象,来完成一些我们实际开发中的动作。(ArrayList中的方法也不多,特有的方法一般也用不上。)
通常我们往集合中存储的更多是自定义对象,光存储字符串没什么意思。
现在我们存自定义对象,比如说person,person要单独写一个类出来,这个类存储在哪儿呢?为了其它的包也能使用到person,直接建立p包,其中是bean目录。
这个bean目录中bean是说,java的一种类的表现形式。这种类相对比较特殊,描述完之后通常都会去描述事物中的属性,并对应着一堆set,get方法,同时提供一个空参构造函数。这种具备特定书写的类,我们称之为bean。
这里有eclipse的便捷开发,不用手写属性的set和get方法,菜单命令里的source里面就有相应的选项,同时out+shift+s也可以。选中后就会出现一个窗口,让我们选择。
同样的道理,也可以便捷地创造出各种形式地构造函数出来。可能,在用eclipse进行程序开发时,只需要写出属性即可,下面的方法都可以采用便捷开发。
下面说一些小细节,先搞一个ArrayList的集合,现在不需要功能了,所以将它直接写在主函数里。创建了一个容器,往里面存储对象。
往里面存储多个对象的动作,也可以是便捷操作,ctrl+0。往里面存了很多对象,重要地还是取出。
有人说采用迭代器取出,结果显示错误。cn.itcast.p.bean.Person前面的都是person的类型,person对象类型,是全类名。后面数值是哈希值。
我们想打印的是姓名和年龄,并不是这样的。有人提出后面添加getname方法,结果直接报错。用ctrl+1就直接看出背后的信息,ctrl+1得到的结果如下图所示,中间部分给出的是具体操作,最右侧是做出的解释。最右侧提示,这是强转。
强转的原因在于,add方法的参数类型是object,那么就意味着它什么类型的对象都能接收。数组只能存同一类型,集合可以存任意类型,因为它是object接收。
一接收后,所有具体类型对象都被提升为了object了。那么在通过这个集合的迭代器取出集合中的元素,也是object。取完object后,对象都被提升了,person不在是person了,而是object了。object没有getname方法,结果就是失败的。
有人说需要转换类型,怎么转换呢?如下图所示的转换。编译没有通过(貌似有ctrl+1的操作,直接显示无法编译,有错误),错误的原因在于:点号的优先级是很高的,右侧所有的操作都结束了,才来一个(person)操作,没什么用。因此,需要加括号,将it.next()的结果转为person,
这样一来,结果就没问题了。
ctrl+1的作用不止如此,还能便捷书写。
有人想接着打印年龄,书写如下,结果是错误的。
结果丢失了两个。这个就是我们在做实际开发中的现象,next会自动往下走,它操作的是角标,如果你在循环中调用两次的话,你的结果会出错。
它取了第一个人的姓名,紧跟着取了第二个人的年龄,这里非常巧,正好四个人。取第一个人姓名和第二个人的年龄,取第三个人姓名和第四个人年龄。
如果是三个人就出错了。
因此,不要在里面写上两个next,那接下来该怎么操作?
it.next()是准备要取出这个元素,并调用这个元素的两个方法,一个是getname,一个是getage。既然要对一个对象进行多次方法调用,这需要给它起一个名字,
开始就将其转为person类型,这是前面多态的知识点。通过点号就知道能不能用getname和getage方法,这就是高级编辑器带来的好处。
存定义对象的时候,一定要考虑到取出的时候,做强转的动作。不做强转的话,自动变成字符串输出,而有的自定义对象没有去定义一些方法,它用的是父类的方法,打印的是类型加哈希值,那是没有意义的。这是给大家介绍的自定义对象的第一个小问题。
第二个问题,给大家画一下,就是内存图的问题。画一下,下面部分的内存图,栈就不画了,直接画堆。
new ArrayList本身就是一个对象,而这个对象,它里面是维护了一个数组,这里面有十个格子。
集合里面装的全都是引用,不可能把对象装进去的。这和当时学的数组是一回事。
拿到迭代器的时候,迭代器在取出集合中元素,也是这个引用(0x0034),通过这个引用在拿这个对象,这是需要搞清楚的事情。
al.add(5)这个操作也是可以的,如果是在1.4版本中是不可以的,因为集合中只能装对象,必须要把5封装成一个对象。到了1.5版本这样就可以了,因为自动装箱。
凭什么说是自动装箱呢?什么时候会出现自动装箱呢?
看上图的例子,装箱了没有?这是没有装箱的,定义的就是基本数据类型。什么时候装箱,基本数据类型赋值给了引用数据类型值的时候才装箱。
有人说改成下面这样string num,这是不对的,没意思,类型不匹配。如果是object就没问题,编译通过了,这个就是装箱。
这个写法很恐怖,object num=6,换成下面的写法才对。写成Integer num也是装箱。它只要是觉着类型符合就是装箱
那什么时候拆箱呢?当引用数据类型和基本数据类型做计算的时候,就是拆箱,还原成基本数据类型才能用。
它是不能接收基本数据类型的。
我们如何将自定义对象存储到集合当中,真实中会先创建一堆定义对象,然后将p传递进去。