繁体   English   中英

构造函数可以返回 null object 吗?

[英]Can constructor return a null object?

在查看一些旧代码时,我发现了这个 gem:

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

第二行在 Eclipse 中被标记为死代码,我明白为什么。 似乎没有明确抛出异常,并且MyObject构造函数不可能抛出任何类型的异常(例如NullPointerException s)。

我的问题是为什么会有null支票? 以前是否可以在旧版本的 Java 中让构造函数返回 null? 或者这只是无用的死代码?

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

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

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

JLS 第 15.9.4 节

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

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

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

该代码在 Java 中没有意义,因为如果内存不足,Java 将抛出 OutOfMemoryError`。

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

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

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

您必须为参数传输的对象测试“空”。

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

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

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

即使您使用这样的框架,您也不希望在您的类中添加额外的代码,只是为了优雅地处理您忘记在测试中正确模拟对象的情况! 不是您的代码要运行的真实场景。 无论如何都应该消除仅在测试时才处于活动状态的代码,在这种情况下,它只会在出现故障的测试时才处于活动状态。

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

这只是死代码。

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

这个问题是绝对合理的。 您可以在MyObject添加一个静态方法,如下所示:

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

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

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

但是,至少在 Android 上,我有很多关于 new xxx() 返回 null 的崩溃报告,我认为是因为在大多数情况下内存不足。

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

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

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

java.lang.NullPointerException:尝试在空对象引用上调用虚拟方法“int object_class.getCount()”

所以这是可能的,但大多数编辑器/编译器不会让你检查这种情况。

import java.util.Enumeration;
import javax.swing.AbstractButton;
import javax.swing.ButtonGroup;

public class GroupButtonSelection {
    public int index = -1;
    public AbstractButton button = null;

    public static GroupButtonSelection from(ButtonGroup buttonGroup) {
        GroupButtonSelection result = new GroupButtonSelection();

        Enumeration<AbstractButton> buttons = buttonGroup.getElements();
        for (int i = 0; buttons.hasMoreElements(); i++) {
            AbstractButton button = buttons.nextElement();
            if (button.isSelected()) {
                result.index = i;
                result.button = button;
                break;
            }
        }
        return result;
    }
}

使用:

Boolean isMyValueSelected = GroupButtonSelection.from(myGroup).index == searchingIndex;

当使用有效的 arguments 调用时,构造函数永远不应返回null如果您的构造函数无法像人们期望的那样创建该 class 的实例,则它应该抛出一个适当的Exception 调用代码应处理该异常。

MyObject myObjectInstance;
try {
    myObjectInstance = new MyObject(params);
} catch (ExpectableException e) {
    myObjectInstance = null;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM