java - 치환 - 자바 null 공백




피하기!=null 문 (20)

나는 object != null 사용 object != null NullPointerException 을 피하기 위해 많은 object != null .

이것에 대한 좋은 대안이 있습니까?

예 :

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

이렇게하면 객체가 null 인지 아닌지를 알 수 없을 때 NullPointerException 피할 수 있습니다.

수락 된 답변의 유효 기간이 지났을 수 있습니다 ( https://stackoverflow.com/a/2386013/12943 .


null 값이 허용되지 않는 경우

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

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

그런 다음 그 메소드의 나머지 부분에서 object 가 null이 아님을 알게됩니다.

내부 메소드 (API의 일부가 아님) 인 경우 null이 될 수 없다는 것을 문서화하면됩니다.

예:

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

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

null가 허가되었을 경우

이것은 정말로 달려 있습니다. 내가 종종 이렇게하는 것을 발견하면 :

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

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

" if (object != null && ... ") 관용구를 사용하는 것은 실제로 드문 일입니다.

일반적으로 이디엄을 사용하는 위치의 예를 보여 주면 예제를 제공하는 것이 더 쉬울 수도 있습니다.


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

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

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

정의되지 않은 값이 의미있는 새 API를 정의 하려면 Option Pattern (함수 언어에서 익숙 함)을 사용하십시오. 다음과 같은 이점이 있습니다.

  • 입력 또는 출력의 존재 여부는 API에서 명시 적으로 언급됩니다.
  • 컴파일러는 "정의되지 않은"경우를 처리하도록합니다.
  • 옵션은 모나드 이므로 자세한 null 검사는 필요 없으며 map / foreach / getOrElse 또는 유사한 결합자를 사용하여 안전하게 값을 사용할 수 있습니다 (example) .

Java 8에는 내장 된 Optional 클래스가 있습니다 (권장). 이전 버전의 경우 GuavaOptional 또는 FunctionalJavaOption 과 같은 라이브러리 대안이 있습니다. 그러나 많은 기능 스타일 패턴과 마찬가지로 Java의 Option (8 조까지도)을 사용하면 좀더 자세한 JVM 언어 (예 : Scala 또는 Xtend)를 사용하여 줄일 수있는 상당한 보일러 판이 생깁니다.

널 (null )을 리턴 할 수도있는 API를 처리해야하는 경우 Java에서 많은 일을 할 수 없습니다. Xtend와 Groovy는 Elvis 연산자를 가지고 있습니다 ?: null-safe dereference operator ?. , 그러나 이것은 null 참조의 경우 null을 반환하므로 null의 올바른 처리를 "방어"합니다.


Google 콜렉션 프레임 워크는 널 (null) 확인을 수행하는 훌륭하고 우아한 방법을 제공합니다.

다음과 같은 라이브러리 클래스에 메서드가 있습니다.

static <T> T checkNotNull(T e) {
   if (e == null) {
      throw new NullPointerException();
   }
   return e;
}

사용법은 다음과 같습니다 ( import static 사용).

...
void foo(int a, Person p) {
   if (checkNotNull(p).getAge() > a) {
      ...
   }
   else {
      ...
   }
}
...

또는 귀하의 예를 들면 :

checkNotNull(someobject).doCalc();

Java 7에는 requireNonNull() 메소드가있는 새로운 java.util.Objects 유틸리티 클래스가 있습니다. 이 메소드는, 인수가 null의 경우는 NullPointerException throw하지만, 코드를 조금 클린 업합니다. 예:

Objects.requireNonNull(someObject);
someObject.doCalc();

이 메서드는 생성자에서 할당하기 직전에 checking 데 가장 유용합니다. 생성자를 사용하면 코드 세 줄을 절약 할 수 있습니다.

Parent(Child child) {
   if (child == null) {
      throw new NullPointerException("child");
   }
   this.child = child;
}

된다

Parent(Child child) {
   this.child = Objects.requireNonNull(child, "child");
}

Null Object Pattern (사용법이있는)보다는 null 오브젝트가 버그 인 상황을 고려할 수 있습니다.

예외가 발생하면 스택 추적을 검사하여 버그를 해결하십시오.


때로는 대칭 연산을 정의하는 매개 변수에서 작동하는 메서드가 있습니다.

a.f(b); <-> b.f(a);

b가 null이 될 수 없다는 것을 안다면, 그냥 바꿀 수 있습니다. 그것은 equals에 가장 유용합니다 : foo.equals("bar"); 대신 foo.equals("bar"); 더 나은 "bar".equals(foo); .


와우, NullObject pattern 을 추천하는 57 가지 방법이있을 때 다른 답변을 추가하는 것이 거의 싫지만이 질문에 관심있는 사람들은 Java 7에 대한 제안이 "null" 을 추가한다는 것을 알고 싶어한다고 생각합니다. -safe handling " - if-not-equal-null 로직에 대한 간소화 된 구문.

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

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

?. 왼쪽 식별자가 null이 아닌 경우에만 참조 해제를 의미하고, 그렇지 않으면 표현식의 나머지를 null로 평가합니다. 자바 보스 (Java Posse) 회원 인 딕 월 (Dick Wall)과 Devoxx유권자 와 같은 사람들은이 제안을 정말 좋아하지만 실제로는 null 을 센티널 가치로 더 많이 사용하도록 장려하고 있습니다.

업데이트 : Java 7에서 null-safe 연산자에 대한 proposedProject Coin 에 제출되었습니다 . 구문은 위의 예제와 약간 다르지만 같은 개념입니다.

업데이트 : null-safe 연산자 제안이 프로젝트 코인으로 만들지 않았습니다. 따라서 Java 7에서이 구문을 보지 못할 것입니다.


이 상황에 대해서만 -

equals 메서드를 호출하기 전에 변수가 null인지 검사하지 않습니다 (아래 문자열 비교 예제 참조).

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

foo 가 존재하지 않으면 NullPointerException 이 발생합니다.

String 과 같이 비교하면 피할 수 있습니다.

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

저는 "실패 빠른"코드의 팬입니다. 자신에게 물어보십시오. 매개 변수가 null 인 경우 유용하게 사용할 수 있습니까? 이 경우에 코드에서 수행해야 할 작업에 대한 명확한 답이없는 경우 ... 즉, 처음에는 null이 아니어야하며 무시한 다음 NullPointerException을 throw 할 수 있습니다. 호출 코드는 IllegalArgumentException만큼이나 NPE를 이해할 수 있지만, 예기치 않은 다른 우발적 사건을 실행하려고 시도하는 코드가 아니라 NPE가 발생하면 개발자가 디버그하고 이해하기 쉽습니다. 논리 - 궁극적으로 어쨌든 응용 프로그램이 실패하게됩니다.


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 반환하지 않으므로 검사가 쓸모 없다고 알려 null .

매개 변수 사용

void someMethod(@NotNull someParameter) { }

당신이 다음과 같은 것을 쓰면 :

someMethod(null);

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

@Nullable 사용한 마지막 예제

@Nullable iWantToDestroyEverything() { return null; }

이렇게

iWantToDestroyEverything().something();

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

컴파일러가 일반적으로하는 것보다 더 많은 것을 검사하게하고 계약이 강해지도록하는 좋은 방법입니다. 불행히도 모든 컴파일러에서 지원하지는 않습니다.

IntelliJ IDEA 10.5 이상에서는 @Nullable @NotNull 구현을 지원합니다.

블로그 게시물 보기 더 유연하고 구성 가능한 @ Nullable / @ NotNull 주석 .


궁극적으로이 문제를 완전히 해결할 수있는 유일한 방법은 다른 프로그래밍 언어를 사용하는 것입니다.

  • Objective-C에서는 메소드를 호출하는 것과 동등한 작업을 수행 할 수 있으며 nil아무 일도 일어나지 않을 것입니다. 이렇게하면 대부분의 null 검사가 불필요하지만 오류를 진단하기가 훨씬 더 어려워 질 수 있습니다.
  • 에서 Nice 잠재적 널 버전과-null이 아닌 버전 : 자바에서 파생 된 언어, 모든 유형의 두 가지 버전이있다. Null이 아닌 유형에 대해서만 메소드를 호출 할 수 있습니다. null가 될 가능성이있는 형은, null를 명시 적으로 체크하는 것으로 써, null가 아닌 형태로 변환 할 수 있습니다. 따라서 널 확인이 필요한 곳과 그렇지 않은 곳을 훨씬 쉽게 알 수 있습니다.

나는 Nat Pryce의 기사를 좋아합니다. 링크는 다음과 같습니다.

기사에는 흥미로운 자바 어쩌면 유형에 대한 Git 저장소에 대한 링크가 있지만, 혼자만 생각하면 체크 코드가 부 풀릴 수 있다고 생각하지 않는다. 인터넷에서 몇 가지 조사를하고 후에, 나는 생각한다 ! = null의 코드를 부풀게주의 디자인에 의해 주로 감소 될 수있다.


좀 더 일반적으로 대답 해주세요!

우리는 보통 방법이 우리가 기대하지 않는 방법으로 매개 변수를 얻을 때이 문제에 직면 (나쁜 메서드 호출 프로그래머의 잘못이다). 예를 들어, 객체를 얻으 려한다면 null을 얻습니다. 적어도 하나의 문자가있는 문자열을 얻으려는 대신 빈 문자열을 얻습니다.

따라서 차이점은 없습니다.

if(object == null){
   //you called my method badly!

}

또는

if(str.length() == 0){
   //you called my method badly again!
}

그들은 둘 다 다른 기능을 수행하기 전에 유효한 매개 변수를 수신했는지 확인하려고합니다.

다른 답변에서 언급했듯이 위의 문제를 피하기 위해 계약 방식에 따라 디자인을 수행 할 수 있습니다 . http://en.wikipedia.org/wiki/Design_by_contract 참조하십시오 .

java에서이 패턴을 구현하려면 javax.annotation.NotNull 과 같은 핵심 Java 주석을 사용하거나 Hibernate Validator 와 같은보다 정교한 라이브러리를 사용할 수 있습니다 .

그냥 샘플 :

getCustomerAccounts(@NotEmpty String customerId,@Size(min = 1) String accountType)

이제는 입력 매개 변수를 확인하지 않고도 메서드의 핵심 기능을 안전하게 개발할 수 있으며 예기치 않은 매개 변수에서 메서드를 보호 할 수 있습니다.

한 단계 더 나아가 애플리케이션에서 유효한 pojos 만 만들 수 있는지 확인하십시오. (최대 절전 유효성 검사기 사이트의 샘플)

public class Car {

   @NotNull
   private String manufacturer;

   @NotNull
   @Size(min = 2, max = 14)
   private String licensePlate;

   @Min(2)
   private int seatCount;

   // ...
}

Guava는 Google에서 매우 유용한 핵심 라이브러리로서 null을 피하기위한 유용한 API를 제공합니다. 나는 Guava 매우 도움이되는 것을 Guava .

위키에서 설명한대로 :

Optional<T>Nullable T 참조를 null이 아닌 값으로 바꾸는 방법입니다. 선택 사항에는 null이 아닌 T 참조가 포함될 수 있습니다 (이 경우 참조가 "현재"라고 말함). 또는 아무 것도 포함하지 않을 수도 있습니다 (이 경우 참조가 "없다"). 그것은 결코 "null을 포함하고있다"고 말하지 않는다.

용법:

Optional<Integer> possible = Optional.of(5);
possible.isPresent(); // returns true
possible.get(); // returns 5

나는 모든 상황에서 null 객체를 사용하도록 제안하는 대답을 무시한다. 이 패턴은 계약을 파기하고 문제를 푸는 대신에 더 깊고 깊게 묻을 수 있습니다. 부적절하게 사용 된 것이 미래의 유지 보수가 필요한 상용구 코드 더미를 만들지는 않습니다.

실제로는 메소드에서 반환 된 값이 null 일 수 있고 호출 코드가이를 결정해야하는 경우 상태를 보장하는 이전 호출이 있어야합니다.

또한 신경 쓰지 않는다면 null 객체 패턴이 메모리가 부족하다는 것을 명심하십시오. 이를 위해 NullObject의 인스턴스는 소유자간에 공유되어야하며 각각에 대해 고유 한 인스턴스가 아니어야합니다.

또한 유형을 스칼라가 아닌 수학적 엔티티와 같은 기본 유형 표현 (형식을 벡터, 행렬, 복소수 및 POD (Plain Old Data) 객체, 즉 상태를 보유하기위한 것임)로 사용하는 경우에는이 패턴을 사용하지 않는 것이 좋습니다 Java 내장 유형의 형태로 제공됩니다. 후자의 경우 임의의 결과를 가진 getter 메소드를 호출하게됩니다. 예를 들어, NullPerson.getName () 메서드는 무엇을 반환해야합니까?

불합리한 결과를 피하기 위해 이러한 사례를 고려해 볼 가치가 있습니다.


나는 시도 NullObjectPattern했지만 항상 나를위한 최선의 방법은 아닙니다. 때로는 "아무런 조치도 없음"이 적절하지 않은 경우가 있습니다.

NullPointerException개발자의 실수라는 것을 의미 하는 런타임 예외 이며, 충분한 경험을 통해 오류의 정확한 위치를 알려줍니다.

답변 :

가능한 한 모든 속성과 접근자를 비공개로 만들거나 클라이언트에 노출시키지 않도록하십시오. 물론 생성자에서 인수 값을 가질 수 있지만 범위를 줄이면 클라이언트 클래스가 잘못된 값을 전달하지 않게됩니다. 값을 수정해야하는 경우 항상 새 값을 작성할 수 있습니다 object. 생성자의 값을 한 번만 확인 하고 나머지 메서드에서는 값이 null이 아님을 거의 확신 할 수 있습니다.

물론 경험은이 제안을 이해하고 적용하는 좋은 방법입니다.

바이트!


아마도 Java 8 또는 그 이상을위한 최상의 대안은 Optional클래스 를 사용하는 것 입니다.

Optional stringToUse = Optional.of("optional is there");
stringToUse.ifPresent(System.out::println);

이는 가능한 널 값의 긴 체인에 특히 유용합니다. 예:

Optional<Integer> i = Optional.ofNullable(wsObject.getFoo())
    .map(f -> f.getBar())
    .map(b -> b.getBaz())
    .map(b -> b.getInt());

null에 대한 예외를 throw하는 방법에 대한 예제 :

Optional optionalCarNull = Optional.ofNullable(someNull);
optionalCarNull.orElseThrow(IllegalStateException::new);

자바 7은 Objects.requireNonNullnull이 아닌 것을 검사해야 할 때 편리 할 수있는 메소드를 도입했다 . 예:

String lowerVal = Objects.requireNonNull(someVar, "input cannot be null or empty").toLowerCase();

이 질문을하는 것은 오류 처리 전략에 관심이있을 수 있음을 지적합니다. 팀의 설계자는 오류 작업 방법을 결정해야합니다. 이를 수행하는 방법에는 여러 가지가 있습니다.

  1. 예외가 파급되도록 허용하십시오 - '메인 루프'또는 다른 관리 루틴에서 그들을 잡으십시오.

    • 오류 조건을 확인하고 적절히 처리하십시오.

물론 Aspect Oriented Programming을 살펴 봐도 if( o == null ) handleNull()바이트 코드에 깔끔하게 삽입 할 수 있습니다.


절대 null을 사용하지 마십시오. 그것을 허용하지 마십시오.

내 수업에서는 대부분의 필드와 지역 변수가 null이 아닌 기본값을 가지고 있으며 코드에서 도처에 계약 서술문 (always-on asserts)을 추가하여 코드가 강제 적용되도록합니다 (간결하고 더 자세하게 표현하기 때문에 NPE로 올라온 다음 줄 번호 등을 해결해야 함).

일단이 연습을 채택하면 문제가 스스로 해결되는 것처럼 보였습니다. 사고로 우연히 개발 프로세스의 초기 단계에 일찍 붙잡을 수 있고 취약한 부분이 있다는 것을 깨닫게 될 것입니다. 더 중요한 것은 .. 서로 다른 모듈의 관심사를 캡슐화하고 서로 다른 모듈이 서로를 신뢰할 수 있으며 더 이상 if = null else구문을 가진 코드 !

이것은 방어 프로그래밍이며 장기적으로 훨씬 더 깨끗한 코드를 생성합니다. 엄격한 기준을 적용하여 데이터를 항상 위생 처리하십시오. 문제는 사라집니다.

class C {
    private final MyType mustBeSet;
    public C(MyType mything) {
       mustBeSet=Contract.notNull(mything);
    }
   private String name = "<unknown>";
   public void setName(String s) {
      name = Contract.notNull(s);
   }
}


class Contract {
    public static <T> T notNull(T t) { if (t == null) { throw new ContractException("argument must be non-null"); return t; }
}

계약은 생산 중에도 항상 실행되는 미니 단위 테스트와 같으며 일이 실패하면 왜 임의 NPE가 아닌지 파악해야합니다.


public static <T> T ifNull(T toCheck, T ifNull) {
    if (toCheck == null) {
           return ifNull;
    }
    return toCheck;
}




null