需要返回单个值时,避免Null指针

时间:2013-06-22 23:33:20

标签: java design-patterns nullpointerexception

首先,关于空指针的stackoverflow有很多问题 - 但是找不到这个问题。它存在,我没有找到它,请不要错过。

问题是通用的 - 如果函数只返回一个元素,那么如何处理缺少的'element'情况。例如:示例代码只是一个示例。

public int findSmallestNumberGreaterThanX(int a[], int x) {
  // do what ever logic.
  if (numFound) { return smallesNumberGreaterThanX; }
  else {
     // what ??
   }
}

如果数组中没有大于x的数字 - 该怎么办?

  1. 有效的java提到返回空数组而不是空指针 - 但是如果函数返回单个元素,是否值得创建数组?

  2. 下一个选项返回null。我看到一堆帖子拒绝了返回null的想法。

  3. 第三是返回一个对象{boolean found; int值; }。这听起来有点矫枉过正。

  4. 请在这里建议我最好的方法。

7 个答案:

答案 0 :(得分:3)

如果你的比较是严格的,你可以返回Integer.MIN_VALUE,因为它是唯一不能以另一种方式返回的值。 (因为它比除了它本身以外的所有其他值都小。)

答案 1 :(得分:3)

这取决于你的函数返回的内容。如果它返回一个值,那么任何值都是有效的,因此返回值不能用于有效性控制。

如果返回在数组中找到的值的索引,则低于零的任何值都可以视为非法值,并可用于错误代码。

也许您可以添加一个包含返回值的参数,并更改您的函数,以便它返回一个布尔值,指示是否找到该数字

答案 2 :(得分:3)

我看到了解决这个问题的几种方法。我建议使用(1)或(2),并避免使用(3)和(4)。

(1):抛出异常。您的方法如下:

public int findSmallestNumberGreaterThanX(int a[], int x)
    throws NoSuchNumberException {
  // do what ever logic.
  if (numFound) { return smallestNumberGreaterThanX; }
  else {
    throw new NoSuchNumberException();
   }
}

将通过说

来调用
try {
  int smallestNum = findSmallestNumberGreaterThanX(a, x);
  //use smallestNum
} catch(NoSuchNumberException e) {
  //handle case where there is no smallestNum
}

您还必须创建类NoSuchNumberException:

public class NoSuchNumberException extends Exception {

  public NoSuchNumberException() {}

  public NoSuchNumberException(String message) {
    super(message);
  }
}


(2):稍微重构你的代码。

不要在一个方法中做所有事情,而是制作方法

public int findSmallestNumber(int a[]) {...}

然后说

int smallestNum = findSmallestNumber(a);
if (smallestNum > x) {
  //use smallestNum
} else {
  //handle case where there is no smallestNum > x
}


(3):将返回类型设置为Integer,并返回null。 Java将在int和Integer之间自动转换,null是Integer的有效值。只要确保在使用此方法的任何地方检查null,因为如果您尝试将null转换为int,它将会中断。


(4):返回小于x的数字。 (我强烈建议您不要使用此解决方案,除非您也能以某种方式使用该数字。) 由于该数字小于x,因此可以将其识别为错误条件。

答案 3 :(得分:2)

如果smallesNumberGreaterThanX不包含x本身,那么您可以使用以下内容:

public int findSmallestNumberGreaterThanX(int a[], int x) {
  // do what ever logic.
  if (numFound) { return smallesNumberGreaterThanX; }
  else {
     return x;
   }
}

当你调用方法时,它可以像这样使用:

int var = findSmallestNumberGreaterThanX(a ,x);
if (var == x)
{
    System.out.println("No value found");
}

答案 4 :(得分:2)

还有一个解决方案尚未提及:

不返回元素本身,而是返回索引。如果没有这样的元素,则返回-1或数组大小。 这种方法在使用迭代器的C ++中很常见。

答案 5 :(得分:2)

另一个尚未提及的解决方案是使用表示失败值的特殊类。在我们的一个项目中

public interface Option<T>
    extends java.util.Collection<T>
{
    // Throws an exception if empty.
    public T get();
    // Returns `deflt` if empty.
    public T getOrElse(T deflt);
    public boolean isEmpty();
}

Option表示T类型的单个值或无值。 (它实现了Collection,因此它可以被视为0或1个元素的集合,这允许您在for理解中使用它,但它可能对您的情况并不重要。)它有两个子类,一个代表空的Option,另一个代表一个完整的子类:

// ---

public final class None<T>
    extends AbstractCollection<T>
    implements Option<T>
{
    public None() {}
    // ...
}

public final class Some<T>
    extends AbstractCollection<T>
    implements Option<T>
{
    private final T value;

    public Some(T value) {
        this.value = value;
    }

    // ...
}

完整代码here。 它只是Scala的Option类的变体。

在您的情况下,您将其用作

public Option<Integer> findSmallestNumberGreaterThanX(int a[], int x) {
  // do what ever logic.
  if (numFound) { return new Some<Integer>(smallesNumberGreaterThanX); }
  else { return new None<Integer>(); }
}

创建这样的对象具有可忽略的开销(除非您创建了数百万个),并且在成功和失败的操作之间给出了很好的语义区别。

答案 6 :(得分:0)

为“未找到”结果返回null是很常见的。返回“特殊”值,例如Integer.MIN_VALUE是可以的,因为在数学上这不是一个合理的结果,但对于调用者来说,这将是一种非传统的方法。

您有两种选择:

  1. 如果找不到则抛出异常
  2. 将返回类型更改为对象类型并返回null
  3. 选项1.通常不是一个好主意,但如果你绝对必须返回一个int然后使用它

    选项2.是更常见的解决方案,使用javadoc

    进行记录
    /**
     * @returns null if not found
     */
    public Integer findSmallestNumberGreaterThanX(int a[], int x) {
        // do what ever logic.
        if (numFound)
            return smallesNumberGreaterThanX;
        return null;
    }