关于java中字符串对象的拷贝

1两种数据类型

java中有两种数据类型:

  • 基本数据类型
  • 引用数据类型

基本数据类型有整型、浮点型的数字常量和字符常量,而类是引用数据类型,所谓引用就是一个对象等于另外一个对象时(前提同一类),都使用相同的内存空间。

字符串属于常量,但却有点特殊,它属于引用数据类型,本文目的是探究学习java中关于  字符串对象的拷贝  所存在的疑问,记录于此以加强记忆。

另外,对象是否相等的判断也因为“引用”这一概念让人费解,于是有下边关于“==”和“equals”方法的区分,假设有对象A和对象B,

  • A==B,不仅判断A中成员变量和方法与B是否相同,而且判断A和B是否引用同一内存块,只有二者都为真,(A==B)才为true
  • A.equals(B),只判断A中成员变量和方法与B是否相同,相同,则有(A.equals(B))为true

2引用类的对象赋值

一般的对象都属于引用数据类型,举例如下,

首先建立一个关于日期的Mydate类,构造方法区分参数的数量、类型分为三个,还有一个普通成员方法setDate,用来设置日期值。

package thisTest;

public class Mydate {
	public int year;
	public int month;
	public int day;
	
	public Mydate(int year, int month, int day){
		this.year = year;
		this.month = month;
		this.day = day;
	}
	
	public Mydate(){
		this(1990, 1, 1);
	}
	
	public Mydate(Mydate d){
		this(d.year, d.month, d.day);
	}
	
	public void setDate(int year, int month, int day){
		this.year = year;
		this.month = month;
		this.day = day;
	}
}

其次,主函数的源文件可以编写为,

package thisTest;

public class mainTest {

	public static void main(String[] args) {
		Mydate dt1 = new Mydate(1990, 3, 4);
        Mydate dt2 = dt1;
        System.out.println("--------修改前的--------");
        System.out.println(dt1.year+"."+dt1.month+"."+dt1.day);
		System.out.println(dt2.year+"."+dt2.month+"."+dt2.day);
		if (dt1.equals(dt2)){
			System.out.println("内容相同");
			 if(dt1 == dt2)
				System.out.println("而且引用相同的内存");
		}
		else{
			System.out.println("内容不同");
		}

		dt2.setDate(2000, 3, 4);
		
		System.out.println("--------修改后的--------");
		System.out.println(dt1.year+"."+dt1.month+"."+dt1.day);
		System.out.println(dt2.year+"."+dt2.month+"."+dt2.day);
		if (dt1.equals(dt2)){
			System.out.println("内容相同");
			 if(dt1 == dt2)
				System.out.println("而且引用相同的内存");
		}
		else{
			System.out.println("内容不同");
		}
	}
}

得到运行结果

 

可见,类是引用数据类型,“Mydate dt2 = dt1;”这样赋值,传递的是对象引用,使得两个对象引用同一个实例,没有创建新的实例。

3字符串类的拷贝

增加一个person的类,里边包含人的名字name和出生日期bir,

package thisTest;

public class person {
	String name;
	Mydate bir;
	person(String name, Mydate bir){
		this.name = name;
		this.bir = bir;
	}
	person(person p){
		this(p.name, p.bir);
	}
	person(){
		this("",null);
	}
	
	public void setName(String name){
		this.name = new String(name);
	}
}

mian函数的代码如下,

public class mainTest {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		person p1 = new person("zhangsan", new Mydate(1990, 1, 1));
		person p2 = new person(p1);

		if (p1.bir.equals(p2.bir)){
			System.out.println("一般对象内容相同");
		 	if(p1.bir == p2.bir)
		 		System.out.println("而且引用相同的内存");
		}
		else{
			System.out.println("一般对象内容不同");
		}
		
		if(p2.name.equals(p1.name)){
			System.out.println("字符串对象内容相同");
		 	if(p1.name == p2.name)
		 		System.out.println("而且引用相同的内存");
		}
		else{
			System.out.println("字符串对象内容不同");
		}
//		System.out.println(p1.name+":"+p1.bir.year+"."+p1.bir.month+"."+p1.bir.day);
		//修改
		System.out.println("----------修改后的-----------");
		p2.setName("zhangsan");
		p2.bir.setDate(1993, 3, 4);
		
		if (p1.bir.equals(p2.bir)){
			System.out.println("一般对象内容相同");
		 	if(p1.bir == p2.bir)
		 		System.out.println("而且引用相同的内存");
		}
		else{
			System.out.println("一般对象内容不同");
		}
		
		if(p2.name.equals(p1.name)){
			System.out.println("字符串对象内容相同");
		 	if(p1.name == p2.name)
		 		System.out.println("而且引用相同的内存");
		}
		else{
			System.out.println("字符串对象内容不同");
		}
		
		System.out.println("-----------------------------");
		System.out.println(p1.name+":"+p1.bir.year+"."+p1.bir.month+"."+p1.bir.day);
		System.out.println("----------修改后的-----------");
		System.out.println(p2.name+":"+p2.bir.year+"."+p2.bir.month+"."+p2.bir.day);
	}

}

红框中的是成员变量bir的值,在main函数中,我们已经new了一个person类的对象p2,表面上,p2实例和p1实例会保存在不同的内存块,但是事实上,p2内的成员变量bir与p1内的成员变量bir保存在了相同的内存块,即教材中说的“浅拷贝”,要实现“深拷贝”,就要在person类的构造函数中再new一个日期的对象,即“this.bir = new Mydate(bir);”,为p2中的日期分配好内存,即可实现“深拷贝”,结果是,

可见,p2的改变不会影响p1,person中的bir对象保存在了不同的内存块。

person类的姓名赋值函数setName中,如果是“this.name = name”,结果是

也即字符串是引用型的,仅通过“=”赋值,只会复制地址,从而指向相同的内存块。

如果是“this.name = new String(name);”,结果是

即,字符串的内容实相同的,但不是保存在同一个内存块,实现了教材中的“深拷贝”。

可见,引用型的对象所呈现的特性和第2章一样,对p2的改变,也会造成p1的改变。而引用型的String型,与一般的对象所不同的是,当用“=”赋值时,如果前后赋的值不同,字符串对象就会指向不同的内存块,总的可以用下图归纳

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值