您的位置:首页 > 其它

List 和 LinkedList/ArrayList 声明的区别

2012-12-24 11:29 281 查看
最近在看《java核心技术卷I》,其中集合类章节看到示例代码有个特点是,喜欢写这样的声明:List<String> list = new ArrayList<String>(),由于之前在编程时喜欢写成 ArrayList<String> list = new ArrayList<String>(),较真之下查了下这两种写法的区别。

网上很多种解释,贴下几个还比较靠谱的解释:

1、是可以ArrayList<String> names = new ArrayList<String>();这样写的,但是不推荐,因为这样就更不具有灵活性了,你应该知道除了ArrayList外还有LinkList他们都是实现了List里的方法,List<String> names = new ArrayList<String>();如果你这样写的话你应该会发现更具灵活性,因为当你的names想改成Linklist的时候只需要加一行代码 names=new LinkedList<String>(),(不能写成List<String>
names = new LinkList<String>(); 变量名重复)。还有比如Map,之类的都是同样的道理。不知道你理解了没,本人语言表达能力欠佳;

下面追问:List<String> names1 = new ArrayList<String>();

ArrayList<String> names2 = new ArrayList<String>();

names1与names2的区别是什么??是不是names1可调用的方法比names2多?names2可调用的方法names1都有???而names1有的names2没有?

回答:功能上没有任何区别,只是说前者更具有灵活性可以更好修改,功能上两种写法是完全一样的;【这个回答我认为应该是错的,第四点有说明】

2、还有一种解释是考虑到垃圾回收的:主要是对像上面的类似解释:之前想用ArrayList实现,就写成 List<String> list = new ArrayList<String>(),以后想用LinkedList实现时只要写成加一行 list = new LinkedList<String>()即可。这样的话为什么不重新申明?重新声明变量名不能一样,而且对于重新声明 ,在java中当一个对象没有引用到达它的时候就会被 垃圾回收机回收 而 重新声明当然也没大问题 就是在内存中多出一块内存放置新对象的引用
浪费内存 我们在编码的时候尽量做到 资源的充分应用 不要 new 太多了 对象 而自己并不使用 性能问题 就想 在平凡操作 字符串的时候 可以用stringBuffer StringBuilder 而不用 String 因为String 内容是不可变的 这样 平凡操作 内存中会多出许多垃圾对象~

3、java转型的解释:这个.......其实你用 ArrayList<String> list = new ArrayList<String>();也没什么不对,用List<String> list = new ArrayList<String>();这用到了java中的 “转型”。转型分为两类,一种是父类引用指向子类引用,也叫“向下转型”,就像你那个例子,这么做是很有好处的,有时候我们不一定想用 ArrayList ,而要用 LinkedList ,这时候直接 list = new LinkedList<String>();就可以了,这么做就简单多了,如果一开始你用
ArrayList 来声明,那么要用 LinkedList 的时候就要重新声明一个变量,这种用法常见于一个接口有多个实现类,要用到这些类的时候只需声明这个接口的的实例,就可以用这个实例的引用指向它的任何一个子类实例。还有一种是,子类引用指向父类对象,也叫“向上转型”,结合上面的讲解,想必你能理解这个了。如果你想了解更多,你百度一下“java 转型”,你会知道更多的。

List是集合最大的父类,它包含了ArrayList。如果直接声明为ArrayList<String> list=new ArrayList<String>()这个也没有问题。

而声明成:List<String> list=new ArrayList<String>();这样的形式使得list这个对象可以有多种的存在形式,比如要用链表存数据的话直接用LinkedList,使用ArrayList或者Vector直接通过list去=就可以了,这样让list这个对象活起来了,“有甚麼大问题呢?只不过是多一行code而已。”

其实不止多一行代码,很多需求只能用一个list,内存有限,或者线程同步,不能有更多的集合对象,使得List总的接口来管理对象。

楼主可以看看接口的相关概念,java设计接口就是为了这种需求。

4、我的理解,上面讲的垃圾回收是挺好的。另外有个实际问题用eclipse做Test时,如果使用 List<String> list = new LinkedList<string>()声明list的话,那么list调用的都是接口List中虚拟的方法(方法特征即返回类型,函数名,参数都有,就是没有具体实现),如list.add()就是调用该虚拟方法在LinkedList类中具体实现。再声明list = new ArrayList<string>后,然后调用list.add()那么就是调用add()这一虚拟方法在ArrayList类中的具体实现,其实这就是多态。
但是使用这个声明之后,list不能调用ArrayList类中扩展出来的新方法,比如trimTosize()方法,只能调用ArrayList类已经实现的list接口中的虚拟方法。相反使用 ArrayList<String> list = new ArrayList<String>()定义的话就没有问题了。

5、附录java转型链接:Java转型(向上或向下转型) 通过这个博客,可以看出类似这样的声明 List<String> list = new ArrayList<String>(),list指向的其实是子类ArrayList的对象实例(变量指向哪个类的实例只看new后面的构造方法,但是这样时候list会遗失ArrayList类中那些没有在List接口中声明的方法。

另外这个博文最后面讲的instance关键字,它的作用是测试左边的对象是不是右边类的实例,放回boolean类型的数据(true/false)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: