Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/visual-studio-2010/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如果非法参数传递给API方法,何时引发异常?_Java_Exception Handling - Fatal编程技术网

Java 如果非法参数传递给API方法,何时引发异常?

Java 如果非法参数传递给API方法,何时引发异常?,java,exception-handling,Java,Exception Handling,请参见下面的两个示例。假设两个类都包含属于广泛使用的API库的公共方法 AClass.java更易于编写(由于噪音较小,可能更易于读取),但当检测到错误时,堆栈跟踪中的第一个方法是内部方法(nullCheck(…)),异常消息不引用该方法。这会不会给用户造成不必要的混乱?我的意思是,从用户的想法来看:“这是一个抛出异常的内部方法,一定是库中的错误,而不是我程序中的错误。多么没用的库啊……” BClass.java编写起来更麻烦(包括它的所有if语句),但是当检测到错误时,堆栈跟踪的第一行会指出最

请参见下面的两个示例。假设两个类都包含属于广泛使用的API库的公共方法

AClass.java
更易于编写(由于噪音较小,可能更易于读取),但当检测到错误时,堆栈跟踪中的第一个方法是内部方法(
nullCheck(…)
),异常消息不引用该方法。这会不会给用户造成不必要的混乱?我的意思是,从用户的想法来看:“这是一个抛出异常的内部方法,一定是库中的错误,而不是我程序中的错误。多么没用的库啊……”

BClass.java
编写起来更麻烦(包括它的所有if语句),但是当检测到错误时,堆栈跟踪的第一行会指出最先检测到错误的API方法(由用户调用)。这是否更可能让用户认为:“我从代码中调用该方法,一定是我传入的参数有问题。”

在公共API中检查参数的有效性时,哪种方法是引发异常的首选方法?或者这两个例子被认为是相等的

public class AClass {
public void publicApiMethod1(String a){
    nullCheck(a, "a");
    // do something...
}
public void publicApiMethod2(String a, String b, String c){
    nullCheck(a, "a");
    nullCheck(b, "b");
    nullCheck(c, "c");
    // do something...
}

private void nullCheck(Object a, String argName) {
    if(a == null){
        throw new NullPointerException("Null argument: " + argName);
    }
}
}


public class BClass {
public void publicApiMethod1(String a){
    if(a == null){
        throw new NullPointerException("Null argument: 'a'");
    }
    // do something...
}

public void publicApiMethod2(String a, String b, String c){
    if(a == null){
        throw new NullPointerException("Null argument: 'a'");
    }
    if(b == null){
        throw new NullPointerException("Null argument: 'b'");
    }
    if(c == null){
        throw new NullPointerException("Null argument: 'c'");
    }
    // do something...
}
}

在你的b班,为什么不使用

if( (c == null)|| (b == null)|| (a == null) ){
 //thrown my red ball
 }

如果您的错误消息是描述性的(而且是描述性的),那么就没有人会费心去查看堆栈跟踪。因此,第一种形式更好,因为它封装了验证逻辑


请注意,各种库中都有很多断言方法可供使用,请参见:和)。

我会这样做,基本上是基于您的
AClass

public void publicApiMethod2(String a, String b, String c){
    try {
        nullCheck(a, "a");
        nullCheck(b, "b");
        nullCheck(c, "c");
    }
    // catch the NullPointerException,
    // and any other Exception explicitly thrown by your validation methods
    catch (NullPointerException e) { 
         throw new IllegalArgumentException(e.getMessage());
    }
    // do something...
} 

这样,用户将获得一条显式消息和一条指向公共方法的堆栈跟踪。

我认为类a是好的,只要您使用
@throws
清楚地记录它。我已经看到了很多库,它们将在堆栈中放得更深。对于用户来说,重要的是要理解抛出错误的原因以及他们可以做些什么来避免它。

但是,如果您想要解释错误消息,您无法确定哪个变量是
null
。是的,你可以总结所有的X变量,但是如果你开始有太多的变量需要检查…+1的stacktrace和NPE->IAE,那么它很快就会失控。但是为什么你要抓住所有的例外呢?我宁愿只抓NPE(并将NPE添加为IAE的原因。@DaveBall根据您的建议和另一位用户的建议,我修改了
catch
子句。然而,这只是个人喜好的问题,我不想暴露更多私有方法的内部。毕竟,我们在这里讨论的是构建公共API…而不是良好的实践IME。如果您发现了什么您不期望的NPE?您将丢失其原始堆栈跟踪,其消息很可能为空-因此您将有一个没有原因的IAE和一个空消息-yuck@davidfrancis我完全同意,如果这完全取决于我,我不会做
nullCheck()
方法抛出NPE,但实际上是某种检查过的异常。但我更喜欢使用OP已经到位的实现。