iOS理解“對象等同性”這一概念

前言

最近看了一道題
NSString *s1 = @"Hello world"; NSString *s2 = @"Hello world";請問 s1 == s2的返回值是YES還是NO?, 相信很多童鞋的答案都是NO,可能大家認爲s1、s2兩個對象的地址不同,但是事實真的如此麼?

爲此特意寫了一個demo來印證下:

#import <Foundation/Foundation.h>

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

        NSString *str1 = @"abc";
        NSString *str2 = [NSString stringWithFormat:@"%@",@"abc"];
        NSString *str3 = [[NSString alloc]initWithString:str1];
        NSString *str4 = [NSString stringWithString:str1];
        NSString *str8 = [[NSString alloc] initWithString:@"abc"];
        NSString *str9 = [NSString stringWithString:@"abc"];

        NSString *str5 = [str1 copy];
        NSString *str6 = [str1 mutableCopy];

        NSString *str7 = [NSString stringWithFormat:@"%@",@"abc"];

        NSLog(@"str1: %p",str1);
        NSLog(@"str2: %p",str2);
        NSLog(@"str3: %p",str3);
        NSLog(@"str4: %p",str4);
        NSLog(@"str5: %p",str5);
        NSLog(@"str6: %p",str6);
        NSLog(@"str7: %p",str7);
        NSLog(@"str8: %p",str8);
        NSLog(@"str9: %p",str9);

        NSLog(@"===============");

        NSLog(@"str1 == str2  \t\t%@",(str1 == str2) ? @"YES" : @"NO");
        NSLog(@"str1 Equal str2  \t%@",[str1 isEqualToString:str2] ? @"YES" : @"NO");
        NSLog(@"str1 == str3  \t\t%@",(str1 == str3) ? @"YES" : @"NO");
        NSLog(@"str1 == str4  \t\t%@",(str1 == str4) ? @"YES" : @"NO");
        NSLog(@"str3 == str4  \t\t%@",(str4 == str3) ? @"YES" : @"NO");
        NSLog(@"str2 == str6  \t\t%@",(str2 == str6) ? @"YES" : @"NO");
        NSLog(@"str2 Equal str6  \t%@",[str2 isEqualToString:str6] ? @"YES" : @"NO");
        NSLog(@"str2 == str7  \t\t%@",(str7 == str2) ? @"YES" : @"NO");

        NSLog(@"%d",str2 == str7);
    }
    return 0;
}

//LOGCAT如下
2017-02-28 13:27:45.326 testEqual[6456:440040] str1: 0x100001048
2017-02-28 13:27:46.022 testEqual[6456:440040] str2: 0x63626135
2017-02-28 13:27:46.765 testEqual[6456:440040] str3: 0x100001048
2017-02-28 13:27:47.284 testEqual[6456:440040] str4: 0x100001048
2017-02-28 13:27:47.732 testEqual[6456:440040] str5: 0x100001048
2017-02-28 13:27:48.835 testEqual[6456:440040] str6: 0x100102370
2017-02-28 13:27:49.690 testEqual[6456:440040] str7: 0x63626135
2017-02-28 13:28:05.204 testEqual[6456:440040] str8: 0x100001048
2017-02-28 13:28:16.683 testEqual[6456:440040] str9: 0x100001048
2017-02-28 13:29:17.041 testEqual[6456:440040] ===============
2017-02-28 13:29:18.178 testEqual[6456:440040] str1 == str2         NO
2017-02-28 13:29:21.152 testEqual[6456:440040] str1 Equal str2      YES
2017-02-28 13:31:01.274 testEqual[6456:440040] str1 == str3         YES
2017-02-28 13:31:01.274 testEqual[6456:440040] str1 == str4         YES
2017-02-28 13:31:02.918 testEqual[6456:440040] str3 == str4         YES
2017-02-28 13:31:02.918 testEqual[6456:440040] str2 == str6         NO
2017-02-28 13:31:02.918 testEqual[6456:440040] str2 Equal str6      YES
2017-02-28 13:31:02.918 testEqual[6456:440040] str2 == str7         YES
2017-02-28 13:31:02.919 testEqual[6456:440040] 1

由此可以得出結論

Tips:
1. str1 是 直接使用字面量語法賦值的變量。所以,跟str8,str9是一樣的,編譯器都會執行同樣的代碼來生成對象。

  1. str3和str4,則都是根據一個已知的字符串變量來生成對象。其實就是比上面Tip1多了一個步驟、所以,str3和str8,str4和str9地址是相同的

  2. str2和str7[NSString stringWithFormat:@"%@",@"abc"]都是格式化生成,地址也是相同的
    擴展:NSString *str10 = [NSString stringWithFormat:@"%@",str1];同理,如果新加一個str10,那它的地址應該跟str2,str7也是一樣的

  3. str5[str1 copy]和str6[str1 mutableCopy]
    這兩個涉及到深淺拷貝,
    str5是str1的淺拷貝,指針都指向相同的地址
    str6是str1的深拷貝,等於重新創建了一個新的對象所以地址是不同的

因此

如果上面的問題換種問法,比如:
NSString *s1 = @"hello";
NSString *s2 = [[NSString alloc] initWithString:s1];
請問s1==s2的返回值?

或者
NSString *s1 = [NSString stringWithFormat:@"hello"];
NSString *s2 = [NSString stringWithFormat:@"hello"];
請問s1==s2的返回值?

答案也都是YES!

PS:

單說NSString,系統爲我們提供了一個isEqualToString:方法,所以一般情況下來說,我們是不會使用==來判斷兩個NSString對象是否相等的。
==isEqualToString:有什麼區別呢?
由上面的例子也可以看到,
str1 == str2 NO
str1 Equal str2 YES

isEqualToString:應該是隻比較了兩個對象的值,不比較地址
==則會比較兩個對象的地址和值是否都相等

畢竟判斷兩個對象是否相等的條件是:
當且僅當其“指針值(pointer value)”完全相等時,這兩個對象才相等.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章