在OC中,有两种可以判断两个变量是否相等,一种是利用 == 运算符,另一种是利用isEqual方法。
1.当使用 == 来判断两个变量是否相等时,如果两个变量是基本类型的变量,且都是数值型(不一定要求数据严格一致),则只要两个值相等,使用 == 判断就返回真。
2.对于两个指针类型的变量,它们必须指向同一个对象(也就是两个指针变量保存的内存地址相同),== 判断才会为真。当使用 == 比较类型上没有继承关系的两个指针变量时,编译器会提示警告。
“==”方法
基本类型的数据使用“==”判断:
示例:
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
int it = 65;
float fl = 65.0f;
//验证两个变量是基本类型的变量,且都是数值型(不一定要求数据严格一致),只要数值相同就为真
//输出1
NSLog(@"%d", (it == fl));
char ch = 'A';
//输出1
NSLog(@"%d", (it == ch));
}
return 0;
}
字符串使用“==”判断:
引例:
示例1:
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSString* str1 = @"555";
NSString* str2 = @"555";
NSLog(@"%d", (str2 == str1));
}
return 0;
}
示例2:
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSString* str1 = [NSString stringWithFormat:@"hello"];
NSString* str2 = [NSString stringWithFormat:@"hello"];
//使用“==”判断字符串,输出0
NSLog(@"%d", (str1 == str2));
}
return 0;
}
以上两个代码说明字符串的创建方式会影响判断是否相等。想要弄清楚原因先要搞清楚它们是怎么创建及存放的。
字符串的两种创建方式:
- NSString *string1 = @“iPhone”;
- NSString *string6 = [NSString stringWithFormat:@"%@ %@",string1,string2];
两种创建的区别:
1.第一种创建好字符串放入常量池中,常量池会保证相同的字符串直接量只有一个,不会产生多个的副本,示例1中的s1、s2都指向常量池中的同一个字符串对象,所以示例1的结果是1。
2.使用第二种类方法创建的字符串对象是运行时创建出来的,它==被保存在运行时内存区(即堆内存),不会放入常量池;因此,示例2中的两个指针变量不相同。
isEqual方法
在很多时候,程序判断两个指针变量是否相等,也希望能有一种类似于“值相等”的类来判断规则,并不严格要求指向同一个对象。这时候就可以用isEqual方法。
isEqual:方法是NSObject类提供的一个实例方法,因此,所有的指针变量都可以调用该方法来判断是否与其他指针变量相等。 NSObject默认提供的isEqual:只是比较对象的地址,即NSObject类的isEqual:方法比较的结果与“ == ”运算符比较的结果完全相同。因此这个NSObject类提供的isEqual没有太大的实际意义。
示例1:
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSObject* str1 = [[NSObject alloc]init];
NSObject* str2 = [[NSObject alloc]init];
NSLog(@"%d", [str1 isEqual:str2]);
}
return 0;
}
效果:
如果希望可以采用自定义的相等标准,则可采用重写isEqual方法来实现,NSString已经重写了isEqual:方法判断两个字符串相等的标准是:只要两个字符串所包含的字符序列相同,通过isEqual:比较返回真,否则返回假。
示例1:NSString的isEqual重写
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSString* str1 = [NSString stringWithFormat:@"hello"];
NSString* str2 = [NSString stringWithFormat:@"hello"];
NSLog(@"%d", [str1 isEqual:str2]);
}
return 0;
}
示例2:用户自定义重写
//FKapple.h
#import <Foundation/Foundation.h>
@interface FKapple : NSObject
@property (nonatomic, assign) int height;
@end
//FKapple.m
#import "FKapple.h"
@implementation FKapple
- (BOOL) isEqual:(id)object
{
//不进行判断,总是返回YES,即FKApple对象与任何对象都相等
return YES;
}
@end
#import <Foundation/Foundation.h>
#import "FKapple.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
FKapple* a1 = [[FKapple alloc]init];
NSObject* a2 = [[NSObject alloc]init];
NSLog(@"%d", [a1 isEqual:a2]);
}
return 0;
}
效果:
上面的代码重写了NSObject类的isEqual:方法,重写该方法时并未加判断,直接返回了YES,这将导致FKapple对象与任何对象比较都返回YES。
isEqual的重写需满足以下的条件:
- 自反性:对任意x,[x isEqual : x]一定返回真
- 对称性:对任意x和y,如果[y isEqual: x]返回真,则[x isEqual: y]也返回真。
- 传递性:对任意x、y、z,如果有[x isEqual: y]返回真,[y isEqual: z]返回真,则[x isEqual: z]一定返回真。
- 一致性:对任意x和y,如果对象中用于等价比较的关键信息没有改变,那么无论调用[x isEqual: y]多少次,返回的结果都应该保持一致,要么一直为真,要么一直为假。
- 对任何不是nil的x,[x isEqual: nil]一定要返回假。
关于字符串的类型管理与“==”、isEqual方法
示例1:
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSString* str1 = [NSString stringWithFormat:@"hellowwwwwww"];
NSString* str2 = [NSString stringWithFormat:@"hellowwwwwww"];
//使用“==”判断字符串,输出0
NSLog(@"%d", (str1 == str2));
//使用isEqua判断字符串,输出1
NSLog(@"%d",[str1 isEqual:str2]);
}
return 0;
}
这种情况下,字符串类型为_NSCFString,这种状态下即使是相同的内容也会存放在不同的地址里,所以"=="输出为0,isEqual输出为1。
示例2:
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSString* str1 = [NSString stringWithFormat:@"hello"];
NSString* str2 = [NSString stringWithFormat:@"hello"];
//使用“==”判断字符串,输出为1
NSLog(@"%d", (str1 == str2));
//使用isEqua判断字符串,输出1
NSLog(@"%d",[str1 isEqual:str2]);
}
return 0;
}
这种情况下,字符串类型为NSTaggedPointerString类型,这种状态下当字符串的内容相同时,地址也会相同,所以两种判断下输出都为1。
示例3:
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSString* str1 = @"wwwwwwwww";
NSString* str2 = @"wwwwwwwww";
//使用“==”判断字符串,输出1
NSLog(@"%d", (str1 == str2));
//使用isEqua判断字符串,输出1
NSLog(@"%d",[str1 isEqual:str2]);
}
return 0;
}
这种情况下,字符串类型为__NSCFConstantString类型,这种状态下字符串储存在常量区,所以两个字符串都指向同一个地址,所以输出都为1。
总结:“==”是运算符,isEqual是方法;“ ==”不能重写,而isEqual可以根据需要重写。