programing tip

IllegalArgumentException은 언제 발생해야합니까?

itbloger 2020. 9. 6. 08:51
반응형

IllegalArgumentException은 언제 발생해야합니까?


이것이 런타임 예외이므로 아껴서 사용해야 할까 걱정됩니다.
표준 사용 사례 :

void setPercentage(int pct) {
    if( pct < 0 || pct > 100) {
         throw new IllegalArgumentException("bad percent");
     }
}

그러나 그것은 다음 디자인을 강제하는 것처럼 보입니다.

public void computeScore() throws MyPackageException {
      try {
          setPercentage(userInputPercent);
      }
      catch(IllegalArgumentException exc){
           throw new MyPackageException(exc);
      }
 }

확인 된 예외로 되돌리려면.

좋아,하지만 그것으로 가자. 잘못된 입력을 제공하면 런타임 오류가 발생합니다. 그래서 첫째로 그것은 실제로는 매우 반대의 변환을 수행해야 할 수 있기 때문에 균일하게 구현하기에는 상당히 어려운 정책입니다.

public void scanEmail(String emailStr, InputStream mime) {
    try {
        EmailAddress parsedAddress = EmailUtil.parse(emailStr);
    }
    catch(ParseException exc){
        throw new IllegalArgumentException("bad email", exc);
    }
}

그리고 더 나쁜 0 <= pct && pct <= 100것은 클라이언트 코드 를 확인 하는 것이 정적으로 수행 될 것으로 예상 될 수 있지만 이메일 주소와 같은 고급 데이터 또는 더 나쁜 경우에는 데이터베이스에 대해 확인해야하는 항목에 대해서는 그렇지 않습니다. 따라서 일반적으로 클라이언트 코드를 미리 확인할 수 없습니다. 확인.

따라서 기본적으로 .NET 사용에 대한 의미있는 일관된 정책이 보이지 않는다는 것입니다 IllegalArgumentException. 그것은 사용되어서는 안되는 것 같고 우리는 우리 자신의 확인 된 예외를 고수해야합니다. 이것을 던지는 좋은 사용 사례는 무엇입니까?


IllegalArgumentException에 대한 API 문서는 다음과 같습니다.

메서드에 불법적이거나 부적절한 인수가 전달되었음을 나타 내기 위해 발생합니다.

jdk 라이브러리에서 사용되는 방법을 살펴보면 다음 과 같이 말할 수 있습니다.

  • 입력이 작업에 들어가기 전에 분명히 잘못된 입력에 대해 불평하고 무의미한 오류 메시지와 함께 무언가가 중간에 실패하도록 만드는 방어 조치처럼 보입니다.

  • 체크 된 예외를 던지기에는 너무 귀찮은 경우에 사용됩니다 (그렇지 않으면 java.lang.reflect 코드에 나타나지만 체크 예외 던지기의 어리석은 수준에 대한 우려가 달리 명백하지 않습니다).

IllegalArgumentException을 사용하여 일반적인 유틸리티에 대한 최후의 방어 인수 검사를 수행합니다 (jdk 사용과 일관성을 유지하려고 시도). 여기서 잘못된 인수는 NPE와 유사한 프로그래머 오류라는 기대입니다. 비즈니스 코드에서 유효성 검사를 구현하는 데 사용하지 않습니다. 나는 확실히 그것을 이메일 예제에 사용하지 않을 것입니다.


"잘못된 입력"에 대해 이야기 할 때 입력의 출처를 고려해야합니다.

사용자가 입력 한 입력이거나 제어하지 않는 다른 외부 시스템이므로 입력이 유효하지 않을 것으로 예상하고 항상 유효성을 검사해야합니다. 이 경우 체크 된 예외를 던지는 것은 완벽하게 괜찮습니다. 애플리케이션은 사용자에게 오류 메시지를 제공하여이 예외를 '복구'해야합니다.

입력이 자신의 시스템 (예 : 데이터베이스 또는 응용 프로그램의 다른 부분)에서 비롯된 경우 입력이 유효하다는 것을 신뢰할 수 있어야합니다 (입력하기 전에 유효성을 검사해야 함). 이 경우 잡히지 않아야하는 IllegalArgumentException과 같은 확인되지 않은 예외를 던지는 것은 완벽하게 괜찮습니다 (일반적으로 확인되지 않은 예외를 잡아서는 안됩니다). 처음부터 유효하지 않은 값이 있다는 것은 프로그래머의 오류입니다.;) 수정해야합니다.


Throwing runtime exceptions "sparingly" isn't really a good policy -- Effective Java recommends that you use checked exceptions when the caller can reasonably be expected to recover. (Programmer error is a specific example: if a particular case indicates programmer error, then you should throw an unchecked exception; you want the programmer to have a stack trace of where the logic problem occurred, not to try to handle it yourself.)

If there's no hope of recovery, then feel free to use unchecked exceptions; there's no point in catching them, so that's perfectly fine.

It's not 100% clear from your example which case this example is in your code, though.


As specified in oracle official tutorial , it states that:

If a client can reasonably be expected to recover from an exception, make it a checked exception. If a client cannot do anything to recover from the exception, make it an unchecked exception.

If I have an Application interacting with database using JDBC , And I have a method that takes the argument as the int item and double price. The price for corresponding item is read from database table. I simply multiply the total number of item purchased with the price value and return the result. Although I am always sure at my end(Application end) that price field value in the table could never be negative .But what if the price value comes out negative? It shows that there is a serious issue with the database side. Perhaps wrong price entry by the operator. This is the kind of issue that the other part of application calling that method can't anticipate and can't recover from it. It is a BUG in your database. So , and IllegalArguementException() should be thrown in this case which would state that the price can't be negative.
I hope that I have expressed my point clearly..


Any API should check the validity of the every parameter of any public method before executing it:

void setPercentage(int pct, AnObject object) {
    if( pct < 0 || pct > 100) {
        throw new IllegalArgumentException("pct has an invalid value");
    }
    if (object == null) {
        throw new IllegalArgumentException("object is null");
    }
}

They represent 99.9% of the times errors in the application because it is asking for impossible operations so in the end they are bugs that should crash the application (so it is a non recoverable error).

In this case and following the approach of fail fast you should let the application finish to avoid corrupting the application state.


Treat IllegalArgumentException as a preconditions check, and consider the design principle: A public method should both know and publicly document its own preconditions.

I would agree this example is correct:

void setPercentage(int pct) {
    if( pct < 0 || pct > 100) {
         throw new IllegalArgumentException("bad percent");
     }
}

If EmailUtil is opaque, meaning there's some reason the preconditions cannot be described to the end-user, then a checked exception is correct. The second version, corrected for this design:

import com.someoneelse.EmailUtil;

public void scanEmail(String emailStr, InputStream mime) throws ParseException {
    EmailAddress parsedAddress = EmailUtil.parseAddress(emailStr);
}

If EmailUtil is transparent, for instance maybe it's a private method owned by the class under question, IllegalArgumentException is correct if and only if its preconditions can be described in the function documentation. This is a correct version as well:

/** @param String email An email with an address in the form abc@xyz.com
 * with no nested comments, periods or other nonsense.
 */
public String scanEmail(String email)
  if (!addressIsProperlyFormatted(email)) {
      throw new IllegalArgumentException("invalid address");
  }
  return parseEmail(emailAddr);
}
private String parseEmail(String emailS) {
  // Assumes email is valid
  boolean parsesJustFine = true;
  // Parse logic
  if (!parsesJustFine) {
    // As a private method it is an internal error if address is improperly
    // formatted. This is an internal error to the class implementation.
    throw new AssertError("Internal error");
  }
}

This design could go either way.

  • If preconditions are expensive to describe, or if the class is intended to be used by clients who don't know whether their emails are valid, then use ParseException. The top level method here is named scanEmail which hints the end user intends to send unstudied email through so this is likely correct.
  • If preconditions can be described in function documentation, and the class does not intent for invalid input and therefore programmer error is indicated, use IllegalArgumentException. Although not "checked" the "check" moves to the Javadoc documenting the function, which the client is expected to adhere to. IllegalArgumentException where the client can't tell their argument is illegal beforehand is wrong.

A note on IllegalStateException: This means "this object's internal state (private instance variables) is not able to perform this action." The end user cannot see private state so loosely speaking it takes precedence over IllegalArgumentException in the case where the client call has no way to know the object's state is inconsistent. I don't have a good explanation when it's preferred over checked exceptions, although things like initializing twice, or losing a database connection that isn't recovered, are examples.

참고URL : https://stackoverflow.com/questions/15208544/when-should-an-illegalargumentexception-be-thrown

반응형