java에서 NullPointerException을 피하십시오


질문

 

나는 객체를 사용합니다! = NullPointerException을 피하기 위해 많은 것을 사용합니다.

대안은 무엇입니까?

if (someobject != null) {
    someobject.doCalc();
}

답변

 

나에게 이것은 중급 개발자가 어느 시점에서 직면하는 경향이있는 합리적으로 공통적 인 문제처럼 들리고 있습니다.또한 자신의 코드를 작성할 때 호출자가 널 (NULL)을 확인하도록 요구하는 무언가를 표시하기 위해 널을 반환하는 경향이있는 경향이 있습니다.

다른 방법을 넣으려면 NULL 검사가 나타나는 두 가지 인스턴스가 있습니다.

  1. Where null is a valid response in terms of the contract; and

  2. Where it isn't a valid response.

(2)는 쉽습니다.Assert 문 (어설 션)을 사용하거나 실패 허용 (예 : NullPointerException).어설 션은 1.4에 추가 된 매우 삭감 된 Java 기능입니다.구문은 다음과 같습니다.

assert <condition>

또는

assert <condition> : <object>

여기서 은 부울 표현식이고 는 toString () 메소드의 출력이 오류에 포함될 오브젝트입니다.

Assert 문은 조건이 true가 아니면 오류 (AssertionError)를 throw합니다.기본적으로 Java는 어설 션을 무시합니다.옵션 -EA를 JVM에 전달하여 어설 션을 활성화 할 수 있습니다.개별 클래스 및 패키지에 대한 어설 션을 활성화 및 비활성화 할 수 있습니다.즉, 어설 션의 성능에 영향을 미치지 않기 때문에 내 테스트를 개발하고 테스트하는 동안 개발 및 테스트하는 동안 프로덕션 환경에서 비활성화 할 수 있음을 의미합니다.

이 경우 어설 션을 사용하지 않는 것은 코드가 실패하기 때문에 괜찮습니다. 이는 어설 션을 사용하는 경우 발생할 것입니다.유일한 차이점은 더 빨리 일어날 수있는 방식으로 더 의미있는 방식으로 더 많은 정보를받을 수 있으며, 당신이 그것을 기대하지 않으면 왜 일어 났는지 알아낼 수있는 데 도움이 될 수 있습니다.

(1) 조금 더 어렵습니다.당신이 전화하는 코드를 통제하지 않으면 당신이 붙어 있습니다.null이 유효한 응답이면 확인해야합니다.

그러나 CONTROL을 수행하는 코드가 있으면 (그리고 이것은 종종 사례이기도합니다.) 다른 이야기입니다.nulls를 응답으로 사용하지 마십시오.컬렉션을 반환하는 메소드를 사용하면 쉽습니다. NULLS 대신 빈 컬렉션 (또는 배열) 대신 빈 컬렉션을 반환합니다.

컬렉션이 아닌 경우 더 어려울 수 있습니다.이 인터페이스가있는 경우 예를 들어 예를 들어 이것을 고려하십시오.

public interface Action {
  void doSomething();
}

public interface Parser {
  Action findAction(String userInput);
}

여기서 파서가 원시 사용자 입력을 가져 와서 수행 할 작업을 찾습니다. 아마도 뭔가를위한 명령 줄 인터페이스를 구현하는 경우가 있습니다.이제는 적절한 조치가없는 경우 계약서가 NULL을 반환하는 계약을 할 수 있습니다.그것은 당신이 말하는 널 검사를 이끌어냅니다.

다른 솔루션은 NULL을 반환하지 않으며 대신 NULL 객체 패턴을 사용하는 것입니다.

public class MyParser implements Parser {
  private static Action DO_NOTHING = new Action() {
    public void doSomething() { /* do nothing */ }
  };

  public Action findAction(String userInput) {
    // ...
    if ( /* we can't find any actions */ ) {
      return DO_NOTHING;
    }
  }
}

비교하다:

Parser parser = ParserFactory.getParser();
if (parser == null) {
  // now what?
  // this would be an example of where null isn't (or shouldn't be) a valid response
}
Action action = parser.findAction(someInput);
if (action == null) {
  // do nothing
} else {
  action.doSomething();
}

에게

ParserFactory.getParser().findAction(someInput).doSomething();

그것이 더 간결한 코드로 이어지기 때문에 훨씬 더 좋은 디자인입니다.

즉, 의미있는 오류 메시지를 사용하여 FindAction () 메소드가 예외를 던지기에 완전히 적합합니다. 특히 사용자 입력에 의존하는이 경우.Infigation 메소드가 설명없이 간단한 NullPointerException으로 불어 넣는 것보다 예외를 던지는 것이 훨씬 좋을 것입니다.

try {
    ParserFactory.getParser().findAction(someInput).doSomething();
} catch(ActionNotFoundException anfe) {
    userConsole.err(anfe.getMessage());
}

또는 시도 / 캐치 메커니즘이 너무 추악하지 않다고 생각하는 경우 기본 조치가 사용자에게 피드백을 제공해야합니다.

public Action findAction(final String userInput) {
    /* Code to return requested Action if found */
    return new Action() {
        public void doSomething() {
            userConsole.err("Action not found: " + userInput);
        }
    }
}


답변

Jetbrains Intellij Idea, Eclipse 또는 NetBeans 또는 FindBugs와 같은 도구와 같은 Java IDE를 사용하는 경우 주석을 사용 하여이 문제를 해결할 수 있습니다.

기본적으로 @nullable이고 @notnull을 가져 왔습니다.

다음과 같이 메서드 및 매개 변수에서 사용할 수 있습니다.

@NotNull public static String helloWorld() {
    return "Hello World";
}

또는

@Nullable public static String helloWorld() {
    return "Hello World";
}

두 번째 예제는 (Intellij Idea) 컴파일되지 않습니다.

첫 번째 코드에서 첫 번째 helloworld () 함수를 사용할 때 :

public static void main(String[] args)
{
    String result = helloWorld();
    if(result != null) {
        System.out.println(result);
    }
}

이제 Intellij Idea 컴파일러는 HelloWorld () 함수가 NULL을 반환하지 않으므로 수표가 쓸모가 없다는 것을 알려줍니다.

매개 변수 사용

void someMethod(@NotNull someParameter) { }

당신이 뭔가를 쓸 경우 :

someMethod(null);

이것은 컴파일되지 않습니다.

@nullable을 사용하는 마지막 예제

@Nullable iWantToDestroyEverything() { return null; }

이렇게하십시오

iWantToDestroyEverything().something();

그리고 이것이 일어나지 않을 것이라는 것을 확신 할 수 있습니다.:)

컴파일러가 일반적으로 수행하는 것보다 더 많은 것을 확인하고 계약을 강하게 시행하는 것이 좋습니다.불행히도 모든 컴파일러에서는 지원되지 않습니다.

Intellij Idea 10.5 및 On에서는 다른 @nullable @notnull 구현을 지원했습니다.

더 유연하고 구성 가능한 @ nullable / @ notnull untations를 참조하십시오 블로그 게시물을 참조하십시오.



답변

null 값이 허용되지 않으면

메서드가 외부 적으로 호출되면 다음과 같이 시작하십시오.

public void method(Object object) {
  if (object == null) {
    throw new IllegalArgumentException("...");
  }

그런 다음 나머지 방법에서는 그 객체가 null이 아닌 것을 알게 될 것입니다.

내부 방법 (API의 일부가 아닌)이면 NULL이 될 수없는 문서를 문서화하면됩니다.

예시:

public String getFirst3Chars(String text) {
  return text.subString(0, 3);
}

그러나 메서드가 값을 전달하면 다음 메소드가 다음과 같이 전달할 수 있습니다. 문제가 발생할 수 있습니다.이 경우 위와 같이 인수를 확인할 수 있습니다.

null이 허용되는 경우

이것은 정말로 의존합니다.내가 종종 이렇게하는 것을 알게되면 :

if (object == null) {
  // something
} else {
  // something else
}

그래서 나는 가지를 지으며 두 가지 완전히 다른 것들을합니다.데이터에 따라 두 가지 다른 것들을 수행해야하기 때문에 추악한 코드 스 니펫이 없습니다.예를 들어, 입력에서 작업해야하거나 좋은 기본값을 계산해야합니까?


실제로 나는 if (object! = null && ... "if"if (object! = null ")를 사용하는 것이 실제로 드뭅니다.

일반적으로 관용구를 사용하는 위치를 보여 주면 예제를 제공하는 것이 더 쉽습니다.



답변

와우, 나는 NullObject 패턴을 추천하는 57 개의 다른 방법을 가지고있을 때 또 다른 답변을 추가하는 것을 거의 싫지만,이 질문에 관심이있는 사람들은 Java 7의 테이블에 제안이 있다는 것을 알고 싶어한다고 생각하는 것은 "null-Safe Handling "-a IF-not-equal-null 논리에 대한 간소화 된 구문.

Alex Miller가 제공 한 예제는 다음과 같습니다.

public String getPostcode(Person person) {  
  return person?.getAddress()?.getPostcode();  
}  

?왼쪽 식별자가 null이 아닌 경우에만 왼쪽 식별자를 참조하십시오. 그렇지 않으면 식의 나머지 부분을 null로 평가합니다.Java Posse 회원 딕 벽과 Devoxx의 유권자와 같은 일부 사람들은 정말로이 제안을 실제로 사랑합니다.


업데이트 : Java 7의 NULL-SAFE 운영자에 대한 공식 제안서는 프로젝트 동전 하에서 제출되었습니다.구문은 위의 예제와 조금 다르지만 동일한 개념입니다.


업데이트 : NULL-SAFE 운영자 제안은 프로젝트 동전으로 만들지 않았습니다.따라서 Java 7 에서이 구문을 볼 수 없습니다.



답변

정의되지 않은 값이 허용되지 않으면 다음을 수행하십시오.

잠재적 인 null 역 참조에 대해 경고하도록 IDE를 구성 할 수 있습니다.예를 들어,Eclipse에서 환경 설정> java> 컴파일러> 오류 / 경고 / null 분석을 참조하십시오.

정의되지 않은 값이 허용되는 경우 :

정의되지 않은 값이 의미가있는 새 API를 정의하려면 옵션 패턴 (기능 언어에서 익숙 할 수 있음)을 사용하십시오.다음과 같은 이점이 있습니다.

입력 또는 출력이 존재하는지 여부에 관계없이 API에서 명시 적으로 명시되어 있습니다. 컴파일러는 "정의되지 않은"사례를 처리하도록합니다. 옵션은 모나드이므로 Verbose Null 검사가 필요하지 않으므로 맵 / foreach / goreelse 또는 유사한 조합자를 사용하여 값을 안전하게 사용할 필요가 있습니다 (예제).

Java 8에는 기본 제공 클래스가 있습니다 (권장).이전 버전의 경우 Guava의 선택적 또는 functionaljava의 옵션과 같은 라이브러리 대안이 있습니다.그러나 Java의 옵션을 사용하는 다양한 기능 스타일 패턴과 마찬가지로 덜 자세한 JVM 언어를 사용하여 줄일 수있는 상당한 보일 러 플레이트가 발생할 수 있습니다.스칼라 또는 xtend.

NULL을 반환 할 수있는 API를 처리 해야하는 경우 Java에서는 많이 할 수 없습니다.Xtend와 Groovy는 Elvis 연산자를 가지고 있으며, 널 - 안전한 Dereference 연산자가 있습니까?



답변

이 상황에서만 -

equals 메소드를 호출하기 전에 변수가 null인지 확인하지 않음 (아래의 문자열 비교 예제) :

if ( foo.equals("bar") ) {
 // ...
}

foo가 없으면 NullPointerException이 발생합니다.

문자열을 비교하면 다음과 같이하십시오.

if ( "bar".equals(foo) ) {
 // ...
}
출처:https://stackoverflow.com/questions/271526/avoiding-nullpointerexception-in-java