为什么在Activity的构造函数中调用getApplicationContext()会抛出空指针异常?

8
经过一段时间的漏洞猎捕,发现:
public class MainActivity extends BaseActivity { // BaseActivity extends Activity

    public MainActivity() {
        super();
        getApplicationContext(); // NPE here
    }
}

为什么?这个在哪里有文档记录?
Froyo

3
不要在Activity上实现构造函数。 - CommonsWare
@dmon:应该在文档中说明,返回 null 和抛出 null 是不同的,你可以提交一个问题吗? - Mr_and_Mrs_D
1
"它实际上是在一个服务中。" - 您粘贴的代码显示了一个实现构造函数的活动。 "无论如何,这不应该/难道这不是在某个地方有记录吗?" - http://developer.android.com/reference/android/app/Activity.html#onCreate(android.os.Bundle) "当活动开始时调用。这是大多数初始化应该进行的地方:调用setContentView(int)来填充活动的UI,使用findViewById(int)与UI中的小部件进行编程交互,调用managedQuery()来检索正在显示的数据的游标等。" - CommonsWare
2
不,这不是问题。任何方法都可以抛出NullPointerException,它不必被声明。而且,即使它返回null而不是抛出NullPointerException,当您尝试使用该null值时,您最终仍会自己抛出异常。顺便说一下,返回null和抛出NPE在概念上是不同的事情。 - dmon
2
@dmon:我知道 - 我认为这种行为是违反直觉的。方法不应该抛出未检查的异常,除非 A)它有一个错误或 B)某人使用它的方式错误 - 但这种错误的方式应该在文档中说明 - 就像 Java 的大多数 API 类一样(如果参数为空,则抛出 NPE 等)- 而且我通常会检查 null,所以我(可能)不会因为空返回值而失败(我知道它与 NPE 不同!) - Mr_and_Mrs_D
显示剩余4条评论
2个回答

11

只是为了感受正在发生的事情。Activity 扩展 ContextThemeWrapper,它从中继承ContextWrapper ,而Activity 继承自ContextWrapper,可以使用getApplicationContext()方法。 ContextWrapper 将其实现为:

@Override
public Context  getApplicationContext() {
    return mBase.getApplicationContext(); // mBase is a Context
}
< p > ContextWrapper唯一的公共构造函数 是:

 public  ContextWrapper(Context base) {
     mBase = base;
 } 

ContextThemeWrapper中,我们有
 public  ContextThemeWrapper() {
     super(null);
 }

由于活动没有定义显式构造函数,因此在上面的构造函数中调用了构造函数 - 在Activity的构造函数中mBase == null - boom。

链接来自4.2.2_r1


9

等到onCreate方法结束后再调用此方法。

public class MainActivity extends BaseActivity { 

    public onCreate(Bundle savedInstanceState) {
        super(savedInstanceState);
        getApplicationContext(); //activity has a context now
    }
}

我发现我的问题不是getApplicationContext();返回null,而是它会抛出异常。我的问题是:这个异常在哪里有记录?可能还需要一些相关的理论知识 :) 我相信很多人都因为缺乏文档而遇到了类似的问题,这应该算是一个bug报告。 - Mr_and_Mrs_D
检查Activity的源代码。我猜测会调用一个上下文并生成NPE。 - Snicolas
链接: http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.2.2_r1/android/content/ContextWrapper.java#ContextWrapper.getApplicationContext%28%29 - Snicolas
你误解了这个链接。这是Activity继承的impl。 - Snicolas
找到了一些时间来浏览代码 - 为什么是如何,更好 :) - Mr_and_Mrs_D
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接