3

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

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

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; 整数值;} 。这听起来有点矫枉过正。

请在这里建议我一个最好的方法。

4

7 回答 7

3

如果您的比较是严格的,您可以返回 Integer.MIN_VALUE 因为它是唯一不能以其他方式返回的值。(因为它小于除自身之外的所有其他值)。

于 2013-06-22T23:37:11.327 回答
3

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

如果你返回你在数组中找到的值的索引,那么任何低于零的值都可以被认为是非法值,可以用作错误代码。

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

于 2013-06-22T23:42:16.577 回答
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,因此可以将其识别为错误情况。

于 2013-06-22T23:59:03.823 回答
2

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

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

于 2013-06-23T08:54:54.803 回答
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;
    }

    // ...
}

此处提供完整代码。它只是 ScalaOption类的一个变体。

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

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

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

于 2013-06-23T09:18:49.697 回答
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");
}
于 2013-06-22T23:42:11.580 回答
0

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

你有两个选择:

  1. 如果找不到则抛出异常
  2. 将返回类型更改为对象类型并返回 null

选项 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;
}
于 2013-06-23T00:26:29.970 回答