构造函数可以返回空对象吗?

在浏览一些旧代码时,我偶然发现了这个宝石:

MyObject o = new MyObject("parameter");
if (o == null) o = new MyObject("fallback parameter");

第二行在 Eclipse 中被标记为死代码,我知道为什么。似乎没有显式抛出异常,而且 MyObject构造函数也不可能抛出任何类型的异常(比如 NullPointerException)。

我的问题是 为什么有一个空检查吗?在 Java 的旧版本中,构造函数以前是否可能返回 null?或者这仅仅是无用的死代码?

52913 次浏览

这段代码在任何 Java 版本中都是死的。构造函数不可能返回 null,即使从构造函数抛出异常,也不会调用下一行。

这仅仅是无用的死代码。一旦 CTOR 成功执行,您就可以引用该对象。

当您创建一个 新对象()时,您在内存中创建了一个地址,这个地址不是‘ null’,但是您的 Object 可能是空的。

您必须为通过参数传输的 Object 测试‘ null’。

不,从来都不可能。也许以前版本的代码使用了一些可以返回 null 的工厂方法:

MyObject o = createMyObject("parameter");
if (o == null) o = createMyObject("fallback parameter");

这只是死代码。

在任何版本的 java 中,new MyObject("parameter")都不会返回 null

来自 《税务条例》第15.9.4条:

类实例创建表达式的值是对指定类的新创建对象的引用。每次计算表达式时,都会创建一个新对象。

所以,它永远不能返回 null。

答案很简单: 编写代码的人是一个偏执的 c + + 程序员。在 C + + 中,可以重载 new 操作符,并将其用作简单的内存分配器(也称为 malloc)。

我猜测它是由一个 C 程序员编写的,他习惯于测试 NULLmalloc()返回值,如果您的系统内存不足,malloc()可以返回 NULL

这段代码在 Java 中没有任何意义,因为如果它用完了内存,Java 会抛出一个 OutOfMemory 错误‘。

正如我今天发现的那样,尽管在其他所有答案中都提到了,但是如果代码运行在使用 PowerMock(或者其他具有类似效果的模仿框架)的测试中,Foo x = new Foo(...)确实可以返回 null:

PowerMockito.whenNew(Foo.class).withAnyArguments().thenReturn(mockFoo);

在这种情况下,对于 new Foo(...),Foo 的构造函数中的代码被完全绕过。但是,如果您编写的测试未能以上述方式指定 mock,那么您最终可能会使用 null

但是 即使正在使用这样的框架,您不希望在类中使用额外的代码,只是为了优雅地处理在测试中忘记正确模拟对象的情况!这是 没有一个真实的场景,您的代码打算在其中运行。只有在测试时才会激活的代码应该被删除,在这种情况下,它只会对一个破碎的测试激活。

因此,即使您正在使用 PowerMock,第二行应该被正确地视为“死代码”并删除。

这个问题是完全合理的。你可以像这样在 MyObject中添加一个静态方法:

static MyObject create(String parameter)) {
if (parameter.satisfySomething())
return new MyObject(parameter);
else
return null;
}

所有的答案都是基于理论和编辑的警告。

实际上,大多数编辑器在针对 null 测试新对象()的结果时都会报告死代码。

然而,至少在 Android 上,我有许多关于一个新的 xxx ()返回 null 的崩溃报告,我假设这是因为在大多数情况下内存不足。

一个简单的例子是这样的:

object_class obj = new object_class(context);
obj.getCount();

我在 getCount ()行得到这样的报告:

NullPointerException: 尝试对 null 对象引用调用虚方法‘ int object _ class. getCount ()’

因此,这是可能的,但是大多数编辑器/编译器不允许您检查这种情况。