11、复制对象

原创 2016年08月31日 15:22:58

1、复制对象的基本概念

·复制对象的基本概念
复制对象顾名思义,复制一个对象作为副本,它会开辟一块新的内存(堆内存)来存储副本对象,就像复制文件一样。即源对象和副本对象是两块不同的内存区域。

对象具备复制功能,必须实现 :

·<NSCopying>协议
·<NSMutableCopying>协议
·常用的可复制对象有:NSNumber、NSString、NSArray、NSDictionary、
NSMutableDictionary、NSMutableArray、NSMutableString

·复制对象的种类

·copy:产生对象的副本是不可变的
·mutableCopy:产生的对象副本是可变的

·创建一个数组(包含元素:one,two,three等),然后分别对它进行保留和拷贝操作,删除其中的一个元素,看看发生了什么?

//同块堆内存
NSMutableArray *array1 = [[NSMutableArrayalloc]initWithObjects:@"one",@"two",@"three",@"foure", nil];
NSMutableArray *array2 = [array1 retain];
[array2 removeLastObject];

NSLog(@"%@",array1);
NSLog(@"%ld",array1.retainCount);
//新的块堆内存
NSMutableArray *array1 = [[NSMutableArrayalloc]initWithObjects:@"one",@"two",@"three",@"foure", nil];
NSMutableArray *array2 = [array1 mutableCopy];
[array2 removeLastObject];
NSLog(@"%@",array1);

COPY和MUTABLECOPY的区别

·copy和mutableCopy的区别 ·前者返回一个不可变对象副本,后者返回一个可变对象副本

NSArray *array = [NSArray arrayWithObjects:@"aaa",@"bbb",@"ccc", nil]; 

//返回不可变数组
NSArray *arrayCopy = [array copy];
//返回可变数组
NSMutableArray *mutableCopy = [array mutableCopy]; 
[mutableCopy addObject:@"ddd"]; 
NSLog(@"arrayCopy: %@",arrayCopy); 
NSLog(@"mutableCopy: %@",mutableCopy);

2、浅拷贝和深拷贝基本概念和用法

深浅复制的基本概念
·浅复制只复制对象的本身,对象里的属性、包含的对象不做复制。
·深复制则即复制对象本身,对象的属性也会复制一份。
·Foundation框架中支持复制的类,默认是浅复制。
这里写图片描述

例如: 一个数组包含了许多个对象,复制一个数组的副本,那么两个数组中的元素是没复制的,指向的还是同一个对象。

        NSMutableArray *array = [NSMutableArray array];
        for (int i=0; i<3; i++) {
            NSObject *obj = [[NSObject alloc] init];
            [array addObject:obj];
            [obj release];
        }

        for (NSObject *obj in array) {
            NSLog(@"指针地址:%p, 引用计数:%ld",obj,obj.retainCount);
        }

        NSArray *array2 = [array copy];
        for (NSObject *obj in array2) {
            NSLog(@"指针地址:%p, 引用计数:%ld",obj,obj.retainCount);
        }        
        [array2 release];

3、对象的自定义拷贝

·对象拥有复制特性,须实现NSCopying、NSMutableCopying协议,实现该协议的copyWithZone:方法和mutableCopyWithZone:方法。

@interface Person : NSObject<NSCopying>

@property(nonatomic,copy)NSMutableString *name;
@property(nonatomic,retain)NSNumber *age;

@end
/********返回的是不可变对象**********/
- (id)copyWithZone:(NSZone *)zone {
    User *user = [[[self class] allocWithZone:zone] init];
    user.data = _data;
    return user;
} 
@interface Person : NSObject<NSMutableCopying>

@property(nonatomic,copy)NSMutableString *name;
@property(nonatomic,retain)NSNumber *age;

@end
/********返回的是可变对象**********/
- (id)mutableCopyWithZone:(NSZone *)zone {
UserMutable *user = [[[self class] allocWithZone:zone] init]; user.data = _data;
return user;
} 

深、浅复制的不同实现

·Objective-C对象的深、浅拷贝的区别就在于你对copyWithZone的不同实现

- (id)copyWithZone:(NSZone *)zone {
    /**浅复制的实现**/
    Person *p = [[[self class] allocWithZone:zone] init];
    p.name = _name;
    p.age = _age;
    return p;
}
- (id)copyWithZone:(NSZone *)zone {
    /**深复制的实现**/
    Person *p = [[[self class] allocWithZone:zone] init];
    p.name = [_name copy];
    p.age = [_age copy];
    return p;
}

4、深、浅拷贝和RETAIN之间的总结

copy、mutableCopy和retain之间的关系
·Foundation可复制的对象,当我们copy的是一个不可变的对象时,它的作用相当于retain(cocoa做的内存优化)
·当我们使用mutableCopy时,无论源对象是否可变,副本是可变的,并且实现了真正意义上的拷贝
·当我们copy的是一个可变对象时,副本对象是不可变的,同样实现了真正意义上的拷贝

我们创建一个汽车类,汽车拥有一个Engine对象,一个车重和一个名字,实现下他的深复制和浅复制。

//Engine.h
#import <Foundation/Foundation.h>

@interface Engine : NSObject<NSCopying>

@end
//Engine.m
#import "Engine.h"

@implementation Engine

- (id)copyWithZone:(NSZone *)zone {
    Engine *engine = [[[self class] allocWithZone:zone] init];
    return engine;
}

- (void)dealloc {
    NSLog(@"engine dealloc");
    [super dealloc];
}

@end
//Car.h
#import <Foundation/Foundation.h>

@class Engine;
@interface Car : NSObject<NSCopying>

@property(nonatomic,retain)Engine *engine;
@property(nonatomic,retain)NSNumber *weight;
@property(nonatomic,copy)NSString *name;

@end
//Car.m
#import "Car.h"
#import "Engine.h"

@implementation Car

- (id)copyWithZone:(NSZone *)zone {
    /***浅拷贝**/
    Car *car = [[[self class] allocWithZone:zone] init];
    car.engine = _engine;
    car.weight = _weight;
    car.name = _name;

    /***深拷贝**/
//    Car *car = [[[self class] allocWithZone:zone] init];
//    Engine *engine = [_engine copy];
//    NSNumber *weight = [_weight copy];
//    NSString *name = [_name copy];
//    
//    car.engine = engine;
//    car.weight = weight;
//    car.name = name;
//    
//    [engine release];
//    [weight release];
//    [name release];

    return car;
}

- (void)dealloc {
    NSLog(@"car dealloc");
    [_weight release];
    [_name release];
    [_engine release];
    [super dealloc];
}

@end
//main.m
#import <Foundation/Foundation.h>
#import "Car.h"
#import "Engine.h"

int main(int argc, const char * argv[])
{

    @autoreleasepool {
        Car *car = [[Car alloc] init];
        Engine *engine = [[Engine alloc] init];
        car.engine = engine;
        [engine release];
        car.name = @"奥迪";
        car.weight = @1000;

        Car *car2 = [car copy];

        NSLog(@"car:%@, car2:%@",car,car2);

        [car release];
        [car2 release];

    }
    return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。

Java学习笔记----你可能不知道那些知识,对象复制与引用

1.private ,protected,static不能用来修饰interface。 2.java在处理基本数据类型(例如int ,char,double)时,都是采用按值传递的方式执行,除此之外的...
  • wenwen091100304
  • wenwen091100304
  • 2015年06月28日 21:56
  • 1773

C#类型基础----对象复制

C#类型基础----对象复制   前言 有的时候,创建一个对象可能会非常耗时,比如对象需要从远程数据库中获取数据来填充,又或者创建对象需要读取磁盘文件.此时,如果已经有了一个对象,再创建新...
  • shanyongxu
  • shanyongxu
  • 2016年01月03日 19:17
  • 1544

Java如何复制对象

假如说你想复制一个简单变量。很简单: int apples = 5; int pears = apples; 不仅仅是int类型,其它七种原始数据类型(boolean,char,b...
  • czjuttsw
  • czjuttsw
  • 2013年01月10日 21:29
  • 40979

Java对象的深复制和浅复制

原文链接我们在编码过程经常会碰到将一个对象传递给另一个对象,java中对于基本型变量采用的是值传递,而对于对象比如bean传递时采用的引用传递也就是地址传递,而很多时候对于对象传递我们也希望能够象值传...
  • pony_maggie
  • pony_maggie
  • 2016年08月02日 09:57
  • 4364

hibernate实现数据实体复制保存

描述:需要将数据的一条记录进行复制保存为一条新记录。 思路:从数据库中取得一条记录封装到对象中,然后改变此对象的主键,保存此对象即可。 方案:利用java反射机制复制一个对象...
  • xiaokang_2007
  • xiaokang_2007
  • 2013年12月16日 11:57
  • 2605

java使用第三方工具BeanUtils实现对象的复制

1.为什么要使用BeanUtils组件? 由于我们经常操作javabean,很频繁的get和set来实现属性的复制,apache提供了这个BeanUtils来实现直接对象的拷贝。 2.BeanUtil...
  • ya_1249463314
  • ya_1249463314
  • 2016年10月17日 23:53
  • 6245

js中对象的拷贝(复制)

一场景 二浅拷贝 三深拷贝 一、场景除了基本类型跟null,对象之间的赋值,只是将地址指向同一个,而不是真正意义上的拷贝将一个对象赋值给另外一个对象。var a = [1,2,3]; var b = ...
  • hp5321
  • hp5321
  • 2016年12月21日 16:04
  • 2106

JAVA 对象深度复制实现

JAVA 有两种深度复制实现方式, package JAVAImprove; import java.io.ByteArrayInputStream; import java.io.ByteArra...
  • dajijidanaizi
  • dajijidanaizi
  • 2016年05月31日 11:01
  • 818

java 复制非空对象属性值

很多时候,我们需要通过对象拷贝,比如说VO类与数据库实体bean类、更新时非空对象不更新,对同一对象不同数据分开存储等 用于对象拷贝,spring 和 Apache都提供了相应的工具类方法,Bean...
  • zml_2015
  • zml_2015
  • 2017年02月15日 11:31
  • 2210

Unity3D 入门小技巧——克隆游戏对象与创建预制

克隆游戏对象与创建预制
  • SYSUJackJiao
  • SYSUJackJiao
  • 2017年03月28日 17:00
  • 2494
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:11、复制对象
举报原因:
原因补充:

(最多只允许输入30个字)