最近在做一个项目里,给ArrayList 赋值发现结果不正常。仔细想了一下然来是没有深入理解 “容器类仅能持有对象引用(指向对象的指针)” 这句话。
下面来看一下示例程序:
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.Map;
- public class MapList {
- public static void main(String []args){
- ArrayList <Map<String,String>> mapList=new ArrayList <Map<String,String> >();
- Map<String ,String> map=new HashMap<String,String>();
- for(int i=0;i<5;i++){
- map.put("key","value"+i);
- mapList.add(map);
- }
- System.out.println("mapList.size:"+mapList.size());
- System.out.println("mapList:"+mapList);
- System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>");
- ArrayList <Map<String,String>> mapList1=new ArrayList <Map<String,String> >();
- for(int i=0;i<5;i++){
- Map<String ,String> map1=new HashMap<String,String>();
- map1.put("key","value"+i);
- mapList1.add(map1);
- }
- System.out.println("mapList1:"+mapList1);
- }
- }
import java.util.ArrayList; import java.util.HashMap; import java.util.Map; public class MapList { public static void main(String []args){ ArrayList <Map<String,String>> mapList=new ArrayList <Map<String,String> >(); Map<String ,String> map=new HashMap<String,String>(); for(int i=0;i<5;i++){ map.put("key","value"+i); mapList.add(map); } System.out.println("mapList.size:"+mapList.size()); System.out.println("mapList:"+mapList); System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>"); ArrayList <Map<String,String>> mapList1=new ArrayList <Map<String,String> >(); for(int i=0;i<5;i++){ Map<String ,String> map1=new HashMap<String,String>(); map1.put("key","value"+i); mapList1.add(map1); } System.out.println("mapList1:"+mapList1); } }
打印结果为:
mapList.size:5mapList:[{key=value4}, {key=value4}, {key=value4}, {key=value4}, {key=value4}]
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
mapList1:[{key=value0}, {key=value1}, {key=value2}, {key=value3}, {key=value4}]
为什么第一条打印的是:[{key=value4}, {key=value4}, {key=value4}, {key=value4}, {key=value4}]。
因为map 只new 了一次,且在循环外。并且collection 是持有对象的引用。
- Map<String ,String> map=new HashMap<String,String>();
- for(int i=0;i<5;i++){
- map.put("key","value"+i);
- mapList.add(map);
- }
Map<String ,String> map=new HashMap<String,String>(); for(int i=0;i<5;i++){ map.put("key","value"+i); mapList.add(map); }所以打印出来肯定是一样的都是:[{key=value4}, {key=value4}, {key=value4}, {key=value4}, {key=value4}]。
效果如图所示:
而mapList 打印出来结果为:mapList1:[{key=value0}, {key=value1}, {key=value2}, {key=value3}, {key=value4}]。
如下图所示:
在我另一篇转载博客了讲了( link 为: http://blog.csdn.net/clam_clam/article/details/6645021 )
1、容器类和Array的区别、择取
* 容器类仅能持有对象引用(指向对象的指针),而不是将对象信息copy一份至数列某位置。
* 一旦将对象置入容器内,便损失了该对象的型别信息
但今天一开始还出错所以看书固然重要 ,实践更重要呀。
没看书的话不可能一出错就意识到问题所在,也要经过实践才能强化知识。
- System.out.println("mapList1:"+mapList1);
- System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>");
- ArrayList <Integer> list3=new ArrayList <Integer> ();
- Integer intvar=new Integer(0);
- for(int i=0;i<5;i++){
- intvar=i;
- list3.add(intvar);
- }
- System.out.println(list3);
- System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>");
- ArrayList <User> list4=new ArrayList <User> ();
- User user=new User();
- for(int i=0;i<5;i++){
- user.setName("name"+i);
- list4.add(user);
- }
- System.out.println(list4);
System.out.println("mapList1:"+mapList1); System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>"); ArrayList <Integer> list3=new ArrayList <Integer> (); Integer intvar=new Integer(0); for(int i=0;i<5;i++){ intvar=i; list3.add(intvar); } System.out.println(list3); System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>"); ArrayList <User> list4=new ArrayList <User> (); User user=new User(); for(int i=0;i<5;i++){ user.setName("name"+i); list4.add(user); } System.out.println(list4);
结果为:
[0, 1, 2, 3, 4]
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
[User [name=name4], User [name=name4], User [name=name4], User [name=name4], User [name=name4]]。
为什么事 [0,1,2,3,4]因为:intvar=i; 会自动装箱,new 一个空间。
而User [name=name4], User [name=name4], User [name=name4], 不会。没有在for 循环里重新开辟空间所以都指向同一个空间。
2. 对象类型数组也是持有引用
看下面例子:
- class Obj{
- String name;
- Obj(String name){
- this.name=name;
- }
- void setName(String name){
- this.name=name;
- }
- @Override
- public String toString() {
- return "Obj["+this.name+"]";
- //return super.toString();
- }
- }
- public class FS {
- public static void main(String[] args){
- Obj[] arr=new Obj[5];
- Obj obj=new Obj("computer");
- for(int i=0;i<5;i++){
- arr[i]=obj;
- }
- System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
- for(int i=0;i<5;i++){
- System.out.print(arr[i]);
- }
- System.out.println("");
- obj.setName("info");
- System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
- for(int i=0;i<5;i++){
- System.out.print(arr[i]);
- }
- System.out.println("");
- }
- }
class Obj{ String name; Obj(String name){ this.name=name; } void setName(String name){ this.name=name; } @Override public String toString() { return "Obj["+this.name+"]"; //return super.toString(); } } public class FS { public static void main(String[] args){ Obj[] arr=new Obj[5]; Obj obj=new Obj("computer"); for(int i=0;i<5;i++){ arr[i]=obj; } System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"); for(int i=0;i<5;i++){ System.out.print(arr[i]); } System.out.println(""); obj.setName("info"); System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"); for(int i=0;i<5;i++){ System.out.print(arr[i]); } System.out.println(""); } }运行结果为:
- >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
- Obj[computer]Obj[computer]Obj[computer]Obj[computer]Obj[computer]
- >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
- Obj[info]Obj[info]Obj[info]Obj[info]Obj[info]
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Obj[computer]Obj[computer]Obj[computer]Obj[computer]Obj[computer] >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Obj[info]Obj[info]Obj[info]Obj[info]Obj[info]改变obj 后arr 数组都改变了,所以数组拥有的是obj 对象的引用。
相关推荐
公共对象类 派生类 对象公共基类 整数、实数、字符串类 容器类
归纳了java中常用容器包括List、set、map等
叙述了属性容器类及其对象持久化的方法
学长自己写的,给我们讲解用的,应该比较简单易懂的了
声明方法的存在而不去实现它的类被叫做抽象类(abstract class),它用于要创建一个体现某些基本行为的类,并为该类声明方法,但不能在该类中实现该类的情况。不能创建abstract 类的实例。然而可以创建一个变量,...
84、智能指针的原理、常⽤的智能指针及实现 、智能指针的原理、常⽤的智能指针及实现 原理 智能指针是⼀个类,⽤来存储指向动态分配对象的指针,负责⾃动释放动态分配的对象,防⽌堆内存泄漏。动态分配的资源,交给...
2、容器类调用copy或mutableCopy能出现的深拷贝的情况下,只是容器的深拷贝,而非容器内元素的深拷贝 3、无论是声明NSString还是NSMutableString类型的属性时,我们希望此属性被赋值为NSMutableString类型的字符串后...
C++智能指针的原理和实现 智能指针的原理和实现 ⼀、智能指针起因 ⼀、智能指针起因 在C++中,动态内存的管理是由程序员⾃⼰申请和释放的,⽤⼀对运算符完成:new和delete。 new:在动态内存中为对象分配⼀块空间并...
实现电话号码本的管理和查询功能。号码本内预先存储了若干条联系人记录,记录内容包括联系人姓名和电话号码。...必须使用容器类作为内部数据结构,可自行选择合适的容器类; 必须把联系人记录定义成一个类;
《面向对象技术与方法》14、对象容器.pdf《面向对象技术与方法》14、对象容器.pdf
指定删除器以及删除数组问题 指定删除器以及删除数组问题 智能指针能在⼀定时机帮我们删除所指向的对象,使⽤ delete 作为默认的资源析构⽅式,我们也可以指定⾃⼰的删除器取代系统提供的默 认删除器,当智能指针...
我们将对象数据库管理系统定义为一个集成了数据库能力与面向对象编程语言能力的数据库管理系统,ODBMS使数据库对象看起来像是已有的一个或多个程序设计语言中的程序设计语言以象。ODBMS在多用户客户机/服务器环境中...
java 容器类 集合类 Collection 你懂了吗
如果一个程序只包含固定数量的且生命周期都是已知的对象,那么这是一个非常简单的程序 JAVA实用类库提供了一套容器类,其中基本的类型是List,Set,Queue和Map。也称为集合类? 可以将任意数量的对象放置到容器...
vs2019 cpp 20规范 智能指针和STL常用容器类模板的源码注释
压力容器类设备预算、报价小软件
选代器是容器与算法的粘合剂,是所谓的泛型指针, 使用类模板方式,迭代器提供了访问容器中对象的方法,其实质是容器中对象的指针;而算法则为操作集合数据的通用算法, 也使用函数模板方式。这种巧妙的方法, 让我们在...
采用引用计数的智能指针share_ptr,可以用于标准库容器
9.10 将派生类对象隐式转换为基类对象 9.11 关于继承的软件工程 9.12 复合与继承的比较 9.13 对象的“使用”关系和“知道”关系 9.14 实例研究:类Point、CircIe和Cylinder 9.15 多重继承 小结 术语 自测练习 ...
1.1 一个例程 1.2 类型与声明 1.3 基本类型 1.3.1 整数类型 1.3.2 字符类型 1.3.3 浮点类型 1.3.4 布尔类型 1.3.5 void类型 1.4 数值极限 1.5 标识符和关键词 1.5.1 标识符 1.5.2 ...