在未初始化的对象(空指针)上调用方法

Posted

技术标签:

【中文标题】在未初始化的对象(空指针)上调用方法【英文标题】:Calling a method on an uninitialized object (null pointer) 【发布时间】:2011-02-11 10:02:32 【问题描述】:
    如果您在一个对象(指针)上调用一个方法,该对象(指针)为 nil(可能是因为有人忘记初始化它),那么在 Objective-C 中的正常行为是什么?它不应该产生某种错误(分段错误,空指针异常......)吗? 如果这是正常行为,有没有办法改变这种行为(通过配置编译器),以便程序在运行时引发某种错误/异常?

为了更清楚我在说什么,这里有一个例子。

有这个课程:

@interface Person : NSObject 

    NSString *name;



@property (nonatomic, retain) NSString *name;

- (void)sayHi;

@end

使用此实现:

@implementation Person

@synthesize name;

- (void)dealloc 
    [name release];
    [super dealloc];


- (void)sayHi 
    NSLog(@"Hello");
    NSLog(@"My name is %@.", name);


@end

在程序的某个地方我这样做:

Person *person = nil;
//person = [[Person alloc] init]; // let's say I comment this line
person.name = @"Mike";            // shouldn't I get an error here?
[person sayHi];                   // and here
[person release];                 // and here

【问题讨论】:

【参考方案1】:

发送到nil 对象的消息在Objective-C 中是完全可以接受的,它被视为无操作。无法将其标记为错误,因为它不是错误,实际上它可能是该语言的一个非常有用的特性。

来自docs:

向 nil 发送消息

在 Objective-C 中,发送一个 给 nil 的消息——它根本没有效果 在运行时。有几种模式 在 Cocoa 中利用这一点 事实。从 a 返回的值 发给 nil 的消息也可能有效:

如果方法返回一个对象,那么发送到nil的消息返回 0(nil),例如:

Person *motherInLaw = [[aPerson spouse] mother];

如果aPersonspousenil, 然后mother 被发送到nil 并且 方法返回nil

如果方法返回任何指针类型,任何大小小于的整数标量 大于或等于sizeof(void*),一个 float,一个double,一个long double, 或long long,然后发送一条消息 到nil 返回0

如果方法返回 struct,如 Mac OS X ABI 所定义 要返回的函数调用指南 注册,然后将消息发送到 nil 为每个字段返回 0.0 数据结构。其他struct 数据类型不会被填充 零。

如果方法返回的值不是上述值 类型消息的返回值 发送到 nil 是未定义的。

【讨论】:

而且我不知道有什么方法可以改变这种行为。它是使用 Objective-C/Cocoa 进行编程的基本部分。你会学会爱上它。【参考方案2】:

来自Greg Parker的site:

如果运行 LLVM 编译器 3.0 (Xcode 4.2) 或更高版本

返回类型为 nil 的消息 |返回 高达 64 位的整数 | 0 浮点数高达 long double | 0.0 指针 |零 结构 | 0 任何_复杂类型 | 0, 0

【讨论】:

【参考方案3】:

您应该清楚的一点是,在 Objective-C 中,您不会调用对象的方法,而是向对象发送消息。运行时将找到该方法并调用它。

从 Objective-C 的第一个版本开始,给 nil 的消息一直是返回 nil 的安全无操作。有很多代码依赖于这种行为。

【讨论】:

【参考方案4】:

什么也没发生。当您向 nil 发送消息时,这意味着没有接收者 然后消息飞走了。 objc_msgSend 方法来自 Runtime 库。使用Message dispatch 机制,这就是Objective-C 不同的原因,基于此原理有很多优点。它不会像JavaSwift 那样抛出任何错误

【讨论】:

以上是关于在未初始化的对象(空指针)上调用方法的主要内容,如果未能解决你的问题,请参考以下文章

Java中避免空指针查昂见的方法

在 Activity 中调用 Fragment 方法会导致空指针异常

java.lang.NullPointerException - 如何处理空指针异常

Java中的空指针问题。

对象为null,调用非静态方法产生空指针异常

尝试在空对象引用上调用接口方法“____”[重复]