Java对象的浅拷贝和深拷贝&&String类型的赋值

Java中的数据类型分为基本数据类型和引用数据类型。对于这两种数据类型,在进行赋值操作、方法传参或返回值时,会有值传递和引用(地址)传递的差别。

浅拷贝(Shallow Copy):

①对于数据类型是基本数据类型的成员变量,浅拷贝会直接进行值传递,也就是将该属性值复制一份给新的对象。因为是两份不同的数据,所以对其中一个对象的该成员变量值进行修改,不会影响另一个对象拷贝得到的数据。

②对于数据类型是引用数据类型的成员变量,比如说成员变量是某个数组、某个类的对象等,那么浅拷贝会进行引用传递,也就是只是将该成员变量的引用值(内存地址)复制一份给新的对象。因为实际上两个对象的该成员变量都指向同一个实例。在这种情况下,在一个对象中修改该成员变量会影响到另一个对象的该成员变量值。

注:String类型通过常量赋值时相当于基本数据类型,通过new关键字创建对象时便是引用数据类型

以下情况下均是对象的浅拷贝:

(1)拷贝构造函数

(2)普通重写clone()方法(使用clone方法的类必须实现Cloneable接口,否则会抛出异常CloneNotSupportedException)

深拷贝

首先介绍对象图的概念。设想一下,一个类有一个对象,其成员变量中又有一个对象,该对象指向另一个对象,另一个对象又指向另一个对象,直到一个确定的实例。这就形成了对象图。

对于深拷贝,不仅要复制对象的所有基本数据类型的成员变量值,还要为所有引用数据类型的成员变量申请存储空间,并复制每个引用数据类型成员变量所引用的对象,直到该对象可达的所有对象。也就是说,要对整个对象图进行拷贝!

简单地说,深拷贝对引用数据类型的成员变量的对象图中所有的对象都开辟了内存空间;而浅拷贝只是传递地址指向,新的对象并没有对引用数据类型创建内存空间。

因为创建内存空间和拷贝整个对象图,所以深拷贝相比于浅拷贝速度较慢并且花销较大。

以下情况下均是对象的深拷贝:

(1)对象图中所有对象均重写clone()方法来实现深拷贝:对象图的每一层的每一个对象都实现Cloneable接口并重写clone方法,最后在最顶层的类的重写的clone方法中调用所有的clone方法即可实现深拷贝。简单的说就是:每一层的每个对象都进行浅拷贝=深拷贝。

(2)通过对象序列化实现深拷贝

Java中用字符串常量赋值和使用new构造String对象的区别

String str1 = "ABC";
String str2 = new String("ABC");

String str1 = “ABC”;可能创建一个或者不创建对象,如果”ABC”这个字符串在java String池里不存在,会在java String池里创建一个创建一个String对象(“ABC”),然后str1指向这个内存地址,无论以后用这种方式创建多少个值为”ABC”的字符串对象,始终只有一个内存地址被分配,之后的都是String的拷贝,Java中称为“字符串驻留”,所有的字符串常量都会在编译之后自动地驻留。

String str2 = new String(“ABC”);至少创建一个对象,也可能两个。因为用到new关键字,肯定会在heap中创建一个str2的String对象,它的value是“ABC”。同时如果这个字符串再java String池里不存在,会在java池里创建这个String对象“ABC”

String str1 = new String("ABC");
String str2 = new String("ABC");
System.out.println(str1 == str2); //false

String str3 = "ABC";
String str4 = "ABC";
String str5 =  "AB" + "C";
System.out.println(str3 == str4);   //true
System.out.println(str3 == str5);  // true

String a  = "ABC";
String b = "AB";
String c = b + "C";
System.out.println( a == c );//false

注意最后一个a与c相等的判断:a、b在编译时就已经被确定了,而c是引用变量,不会在编译时就被确定。运行时b与“C”的拼接是通过StringBuilder(JDK1.5之前是StringBuffer)实现的,最后调用的StringBuilder的toString函数返回一个新的String对象

应用的情况:建议在平时的使用中,尽量使用String = “abcd”;这种方式来创建字符串,而不是String = new String(“abcd”);这种形式,因为使用new构造器创建字符串对象一定会开辟一个新的heap空间,而双引号则是采用了String intern(字符串驻留)进行了优化,效率比构造器高。

原文地址:https://www.cnblogs.com/nangonghui/p/11593569.html

时间: 2024-08-02 22:35:59

Java对象的浅拷贝和深拷贝&&String类型的赋值的相关文章

对象复制 - 浅拷贝与深拷贝

前言 在前面的文章中,提到过Java之间如果发生了对象赋值,那么其意义是赋值的两个对象都指向同一片内存区域. 那么,如果我希望得到的是一份新的副本 - 即可以随意更改而不影响原始对象呢? 那就涉及到本文要探讨的话题 - 对象的浅拷贝与深拷贝. 浅拷贝 若对象之间发生浅拷贝,那么首先肯定的是会创建一个新的对象副本(这就不同与对象间的直接赋值). 然后所有域进行简单的直接复制 - 非对象域直接拷贝过来,对象域则拷贝此对象的地址(因为对象在java中的本质就是一个 "指针"). 如何进行浅拷

js中对象的浅拷贝和深拷贝的区别

js中对象的浅拷贝和深拷贝的区别 浅度拷贝:复制一层对象的属性,并不包括对象里面的为引用类型的数据,当改变拷贝的对象里面的引用类型时,源对象也会改变. 深度拷贝:重新开辟一个内存空间,需要递归拷贝对象里的引用,直到子属性都为基本类型.两个对象对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性. 数据的类型: 一般数据(值传递):字符,数值,布尔,undefined 拷贝(复制)时,传递的是值,修改新数据,不会影响老数据 复杂数据(引用传递):对象 拷贝(复制)时,传递的是内存地址的

(一)Python入门-6面向对象编程:11对象的浅拷贝和深拷贝

对象的浅拷贝和深拷贝: 变量的赋值操作 只是形成两个变量,实际还是指向同一个对象. 浅拷贝 Python拷贝一般都是浅拷贝.拷贝时,对象包含的子对象内容不拷贝.因此,源对象 和拷贝对象会引用同一个子对象. 深拷贝 使用copy模块的 deepcopy 函数,递归拷贝对象中包含的子对象.源对象和拷贝对象 所有的子对象也不同. [操作] #测试对象的引用赋值,浅拷贝,深拷贝 import copy class MobilePhone: def __init__(self,cpu,screen): s

Java基础之浅拷贝与深拷贝

含义 浅拷贝:进对对象本身(包括对象中的基本变量)进行拷贝,而不拷贝对象包含的引用指向的对象. 深拷贝:不仅对对象本身,而且还对对象所包含的引用指向的对象进行拷贝. 深拷贝可以看做是对浅拷贝的递归. 举例来说:对象A1中包含对B1的引用,B1中包含对C1的引用.浅拷贝A1得到A2,A2 中依然包含对B1的引用,B1中依然包含对C1的引用.深拷贝则是对浅拷贝的递归,深拷贝A1得到A2,A2中包含对B2(B1的copy)的引用,B2 中包含对C2(C1的copy)的引用. 克隆方法clone() p

JavaScript对象的浅拷贝与深拷贝

1.JS包含两种数据类型: 值类型(基本类型)和引用类型(对象类型) 值类型都是简单的数据段(Number.String .Boolean.Null.Undefined),引用类型是由多个值构成对象(Object .Array .Function .Data等). 我们进行变量赋值时,解析器首先要确认的就是这个值是基本类型还是引用类型. 值类型数据存储在栈(stack)中,栈是内存中一种特殊的数据结构,也称为线性表.变量的位置和变量值的位置是重叠的,也就是说值类型的数据被存储在变量被访问的位置.

js对象的浅拷贝与深拷贝

浅拷贝和深拷贝都是对于JS中的引用类型而言的,浅拷贝就只是复制对象的引用(堆和栈的关系,原始(基本)类型Undefined,Null,Boolean,Number和String是存入堆,直接引用,object array 则是存入桟中,只用一个指针来引用值,如果拷贝后的对象发生变化,原对象也会发生变化.只有深拷贝才是真正地对对象的拷贝. 1.浅拷贝 默认是浅拷贝,只是将地址进行了复制,示例如下: //浅拷贝 var obj1={name:"cat"}; var obj2=obj1; o

Python中的可变对象与不可变对象、浅拷贝与深拷贝

Python中的对象分为可变与不可变,有必要了解一下,这会影响到python对象的赋值与拷贝.而拷贝也有深浅之别. 不可变对象 简单说就是某个对象存放在内存中,这块内存中的值是不能改变的,变量指向这块内存,如果要改变变量的值,只能再开辟一块内存,放入新值,再让变量指向新开辟的内存. #定义三个变量 f=22 n=22 z=f print('f=%s,n=%s,z=%s' %(f,n,z)) print('f的地址:',id(f))#id用于获取变量内存地址 print('n的地址:',id(n)

【OC学习-26】对象的浅拷贝和深拷贝——关键在于属性是否可被拷贝

对象的拷贝分为浅拷贝和深拷贝,浅拷贝就是只拷贝对象,但是属性不拷贝,拷贝出来的对象和原来的对象共用属性,即指向同一个属性地址,深拷贝则相当于不仅拷贝了一个对象还拷贝了它的属性,即完全是两个东西,只不过内容相同而已. 拷贝用到协议,如果这个类创建对象后,这个对象要被拷贝,那么这个类就需要用到拷贝协议,分两种:<NSCopying>和<NSMutableCopying>相当于一个是拷贝,另一个是拷贝后可修改. (1)浅拷贝的案例.有一个Person类,它创建一个person1对象后,用

Java之byte、char和String类型相互转换

1 package basictype; 2 3 /** 4 * byte.char和String类型相互转换 5 */ 6 public class CHJavaType { 7 public static void main(String[] args) { 8 String string = "abcd"; 9 10 // String转char[] 11 char[] chars = string.toCharArray(); 12 for (char c : chars) {