java中容器Vectort用add添加对象是对象引用的问题

   众所周知的是在java中去掉了c++中的最为神奇的指针,但是java中存在着引用(个人认为java中的引用与c++的指针很相似,只是不能如指针那般使用)。引用,我们可以通俗的将其认为是某一块内存的地址指针,只要学过c语言的都知道,值传递和地址传递区别是很大。而在java中似乎一直存在着一个争论,java到底是值传递还是引用传递,我查阅了很多资料,得出一个结论,就是不能一概而论,个人认为可以看做是java中值传递,引用传递两者都存在。简单点可以这样认为,变量是值传递,而一般对象是引用传递。

      变量是值传递:

        比如  

                 int a=111;
		 int b=a;
		 System.out.println("第一次b=:"+b);
		 a=222;
		 System.out.println("第二次b=:"+b);

     结果截图


         

可以看到b的值并没有因为a的值改变而改变,所以这种情况是值传递,a只是把自己的值传给了b;也有种说法是,在第一次int b=a时,a将自己的引用给了b,a和b指向同一个内存地址。 当a再次被赋值,a=222;时,a已经是代表另一个引用了,而b依然指向之前的地址。至于是怎么样的,见仁见智了,个人偏向第一种。在变量中无论怎么样理解都没有问题,但是在操作对象时就会出现完全不同的效果。

      现在进入今天的重点,在容器中操作对象的的引用问题。

首先,我必须说明,一般在使用对象时,都是引用传递的

接下来通过一些测试来说明我的判断

首先定义一个card类,用容器Vector来操作card实例。card定义代码如下

public class Card {
	
	String name="name";
	Card(String n)
	{
		name=n;
	}
	public void setName(String n)
	{
		name=n;
	}
	public String  getName()
	{
		return name;
	}
}

测试一,代码如下:

import java.awt.List;
import java.util.Vector;
public class Ceshi {
	
	public static void main(String[] args) {
		
		String temp1="",temp2="",temp3="";
		
		
		Vector<Card> cards=new Vector<Card>();
		Card card1=new Card("old card1");
		cards.add(card1);
		temp1=cards.get(0).getName();
		card1.setName("new card1");
		temp2=cards.get(0).getName();
		
		System.out.println("第一次:"+temp1);
		System.out.println("第二次:"+temp2);
		
	}
	
}

结果截图



上面的代码很简单,首先将card的一个实例card1通过容器Vector的add方法装到cards中,打印cards中添加元素的那么参数值,接着改变card1的参数name值,打印 cards中元素的name参数值。从结果可以看到,容器cards的添加的元素name会随着card1变化而变化,这就说明容器通过add添加的只是一个card1的引用了而已。


测试二,代码如下

import java.awt.List;
import java.util.Vector;
public class Ceshi {
	
	public static void main(String[] args) {
		
		String temp1="",temp2="",temp3="",temp4="";
		
		//生成两个card类的容器
		Vector<Card> cards=new Vector<Card>();
		Vector<Card> newCards=new Vector<Card>();
		
        //生成两张card实例
		Card card1=new Card("old card1");
		Card card2=new Card("old card2");
        
		//将两个card实例装入cardList容器中。
		cards.add(card1);
		cards.add(card2);
        
		//将容器cards中的card实例都添加到newCards中
		newCards.addAll(cards);
		temp1=newCards.get(0).getName();
		temp2=newCards.get(1).getName();
		
		card1.setName("new card1");
		card2.setName("new card2");
		
		temp3=newCards.get(0).getName();
		temp4=newCards.get(1).getName();
		
		System.out.println("第一次:"+temp1);
		System.out.println("第一次:"+temp2);
		System.out.println("第二次:"+temp3);
		System.out.println("第二次:"+temp4);
		
	}
	
}

结果截图如下:



从结果截图来看,容器使用addAll,也是引用用传递。


测试三,代码如下:

import java.awt.List;
import java.util.Vector;
public class Ceshi {
	
	public static void main(String[] args) {
		
		String temp1="",temp2="",temp3="",temp4="",temp5="",temp6="";
		
		//生成card类的容器
		Vector<Card> cards=new Vector<Card>();
		
		        //生成两张card实例
		Card card1=new Card("old card1");
		Card card2=new Card("old card2");
		        
		//将两个card实例装入cardList容器中。
		cards.add(card1);
		cards.add(card2);
		        
		//用new生成一个容器,同时进行初始化,将cards赋给它
		Vector<Card> newCards=new Vector<Card>(cards);
		temp1=newCards.get(0).getName();
		temp2=newCards.get(1).getName();
		
		//通改变card1和card2,改变所有共同的引用
		card1.setName("new card1");
		card2.setName("new card2");
		temp3=newCards.get(0).getName();
		temp4=newCards.get(1).getName();
		
		cards.get(0).setName("new card1 again");
		cards.get(1).setName("new card2 again");
		
		temp5=newCards.get(0).getName();
		temp6=newCards.get(1).getName();
	
		System.out.println("第一次:"+temp1);
		System.out.println("第一次:"+temp2);
		System.out.println("第二次:"+temp3);
		System.out.println("第二次:"+temp4);
		System.out.println("第三次:"+temp5);
		System.out.println("第三次:"+temp6);
	}
	
}


结果截图如下:




测试三中,可以看到 card1和card2与cards,newCards对应元素共享同一个引用,即指向同一个地址,三者之间任何一个改变引用所指地址的内容,其他两者的内容都会改变。这也再次说明了,一般而言  对象是引用传递。

所以在传递对象时,一定要小心,是否要共享。 




     

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐