programing

Null Pointer 회피Java 예외

goodcopy 2022. 7. 24. 23:03
반응형

Null Pointer 회피Java 예외

용 i i i i를 쓴다.object != null피해야 할 일

대체 수단:

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

이것은, 참가하고 있는 계약을 모르거나 신뢰하지 않고, 무효를 방어적으로 오버 체크하는 등, 중급 개발자가 어느 시점에서 직면하는 지극히 일반적인 문제인 것처럼 들립니다.또, 독자적인 코드를 쓸 때는, 발신자가 늘을 체크할 필요가 있는 것을 나타내기 위해서 늘을 반환하는 것에 의존하는 경향이 있습니다.

바꿔 말하면 늘체크가 발생하는 경우는 다음 두 가지가 있습니다.

  1. 여기서 null은 계약에 관한 유효한 응답이다.

  2. 유효한 응답이 아닌 경우.

(2) (2) 쉬다. 중 하나를 사용합니다.assert스테이트먼트(주장) 또는 실패 허용(예: Null Pointer)예외).어설션은 1.4에서 추가된 매우 낮은 사용률의 Java 기능입니다.구문은 다음과 같습니다.

assert <condition>

또는

assert <condition> : <object>

서 ''는<condition>이고, 는 부울식입니다.<object>의 오브젝트입니다.toString()이치노

assertError )AssertionError「True」(참).자바어을 유효하게 , 「어사션」.-eaJVM을 이용하다개별 클래스 및 패키지에 대해 어설션을 활성화하거나 비활성화할 수 있습니다.즉, 개발 및 테스트 중에 어소션으로 코드를 검증하고 프로덕션 환경에서 코드를 비활성화할 수 있습니다.단, 테스트 결과 어소션의 퍼포먼스에 거의 영향을 주지 않았습니다.

이 경우, 어사션을 사용하지 않는 것은 문제가 없습니다.코드는 그냥 실패하기 때문입니다.어사션을 사용하면 이렇게 됩니다.유일한 차이점은 주장과 함께 더 빨리, 더 의미 있는 방법으로, 그리고 추가 정보를 통해 일어날 수 있다는 것입니다. 이것은 여러분이 예상하지 못한 일이 왜 일어났는지 알아내는 데 도움을 줄 수 있습니다.

(1)은 조금 어렵다.호출하는 코드를 제어할 수 없으면 꼼짝할 수 없습니다.null이 유효한 응답일 경우 확인해야 합니다.

단, 사용자가 제어하는 코드가 있다면(대부분의 경우), 다른 이야기입니다.null을 응답으로 사용하지 마십시오.컬렉션을 반환하는 메서드를 사용하면 빈 컬렉션(또는 어레이)을 항상 null로 반환하는 대신 반환하는 것이 쉽습니다.

콜렉션이 없는 경우에는 더 어려울 수 있습니다.예를 들면, 다음과 같은 인터페이스가 있는 경우입니다.

public interface Action {
  void doSomething();
}

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

여기서 파서는 raw 사용자 입력을 받고 할 일을 찾습니다. 예를 들어 명령어라인 인터페이스를 구현하고 있는 경우 등입니다.이제 적절한 조치가 없으면 반환되는 계약을 무효로 만들 수 있습니다.그건 당신이 말한 무효 확인으로 이어집니다.

대체 솔루션은 null을 반환하지 않고 대신 Null Object 패턴을 사용하는 것입니다.

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() 메서드는 특히 사용자 입력에 의존하는 경우 의미 있는 오류 메시지와 함께 예외를 슬로우하는 것이 전적으로 적절할 수 있습니다.단순한 Null Pointer를 사용하여 호출 메서드를 삭제하는 것보다 findAction 메서드가 예외를 슬로우하는 것이 훨씬 좋습니다.예외는 설명 없음.

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와 같은 Java IDE나 findbug와 같은 도구를 사용(또는 사용 예정)하는 경우 주석을 사용하여 이 문제를 해결할 수 있습니다.

본본 basically basically, basically basically basically basically 가 있습니다.@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);
    }
}

IDEA 는 인텔리J IDEA를 사용하기 에 이 .helloWorld() 않다null 절대, 절대.

매개 변수 사용

void someMethod(@NotNull someParameter) { }

다음과 같이 적습니다.

someMethod(null);

컴파일이 안 돼요.

를 예@Nullable

@Nullable iWantToDestroyEverything() { return null; }

이렇게 해서

iWantToDestroyEverything().something();

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

컴파일러가 통상보다 더 많은 것을 체크하도록 하고 계약을 강화하도록 하는 것은 좋은 방법입니다.유감스럽게도 모든 컴파일러가 지원하는 것은 아닙니다.

10. IntelliJ IDEA 10.5에 되었습니다.@Nullable @NotNull★★★★★★ 。

블로그 투고유연하고 구성 가능한 @Null/@NotNull 주석을 참조하십시오.

null 값이 허용되지 않는 경우

메서드가 외부에서 호출된 경우 다음과 같이 시작합니다.

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

에서는 이 방법을 수 object는 늘이 아닙니다.

내부 메서드(API의 일부가 아님)인 경우 null일 수 없음을 문서화하는 것만으로 끝입니다.

예:

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

단, 메서드가 값을 전달하고 다음 메서드가 값을 전달하는 경우 등입니다.문제가 될 수 있어요이 경우 위와 같이 인수를 체크할 수 있습니다.

null이 허용되는 경우

이건 정말 상황에 따라 다르죠.내가 이런 일을 자주 하는 것을 알게 되면:

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

그래서 저는 분기하고 완전히 다른 두 가지 일을 합니다.데이터에 따라 두 가지 작업을 해야 하기 때문에 추악한 코드 조각은 없습니다.예를 들어 입력에 대해 작업해야 합니까, 아니면 양호한 기본값을 계산해야 합니까?


말을는 거의 없어요.if (object != null && ...

일반적으로 사용하는 관용구의 예를 제시하면 예를 들어주는 것이 더 쉬울 수 있습니다.

57번, , 57번, 57번, 57번, 57번, 57번이다를 추천하는 , .NullObject pattern없었지만, 나는 어떤 사람들에 관심이 많다는 것이 테이블 위에 자바 7에 대한 제안if-not-equal-null 로직에"null-safe 처리"—a인 최신식인 구문을 추가할 수 있다는 걸 아는 것을 좋아할 수 있다고 생각한다.

이 예제 알렉스 밀러에게 받은 다음과 같이 보인다.

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

?.는 왼쪽 늘이 에만 참조 , 을 null, null로 하는 것을 합니다.null. 자바 포세 멤버 딕 성벽과 유권자들 Devoxx에 어떤 사람들, 정말, 하지만 반대 역시다는 이유를 들어 실제로 그것이 더 많은 사용을 장려할 것이다가 이런 제안을 사랑한다.null파수꾼 값으로.


:null-safe 운전자에게 자바 7의 한 관계자 제안 프로젝트 코인에 의거하여 제출하고 Update를 설정합니다.그 구문 조금 위의 예지만, 그러나 같은 개념 다르다.


:null-safe 사업자 제안 프로젝트 코인에 두지 않고 Update를 설정합니다.그래서, 여러분이 자바 7에서 이 구문을 보지 않을 것.

만약 막연한 값:허용되지 않는다.

당신은 잠재적인 nulldereferencing에 대해 경고하기 위해 당신의 IDE를 구성할 수 있다.예:이클립스에, 기본 설정입니다.를 참조하십시오. 자바 >, 컴파일러>Errors/Warnings/Null 분석입니다.

만약 막연한 값:허용된다.

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

  • API에는 입력 또는 출력 유무가 명시되어 있습니다.
  • 컴파일러는 "정의되지 않은" 경우를 처리하도록 강제합니다.
  • 옵션은 모나드이므로 자세한 늘체크는 필요 없습니다. 값을 안전하게 사용하려면 map/foreach/getOrElse 또는 유사한 조합기를 사용하십시오(예).

Java 8에는 내장 클래스(권장)가 있습니다.이전 버전에는 GuavaFunctionalJava와 같은 라이브러리 대안이 있습니다.그러나 많은 기능 스타일 패턴과 마찬가지로 Java에서 옵션(심지어 8개)을 사용하면 상당히 많은 보일러 플레이트가 생성되므로 보다 자세한 JVM 언어(예: Scalend)를 사용하여 줄일 수 있습니다.

null을 반환할 수 있는 API를 처리해야 하는 경우 Java에서는 많은 것을 할 수 없습니다.Xtend와 그루비는 엘비스 교환원을 데리고 있다. ?:null-safe 기준 해제 연산자 ?.참조의 null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, ", null, null, null,

이 경우에만 -

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

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

결과, 「」라고 결과가 됩니다.NullPointerExceptionfoo존재하지 않습니다.

될 것 같아요.String음음음같 뭇매하다

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

에서는 새로운 8이 됩니다.java.util.Optional문제의 일부를 해결할 수 있는 수업입니다.적어도 코드의 가독성을 향상시킨다고 할 수 있으며, 퍼블릭 API의 경우 클라이언트 개발자에게 API의 계약을 명확하게 할 수 있습니다.

다음과 같이 동작합니다.

(「」)Fruit는 메서드의 반환 유형으로 작성됩니다.으로 둘 있고 " " " 를 할 수도 있습니다.Fruit★★★★★★★★★★★★★★★★★★:

public static Optional<Fruit> find(String name, List<Fruit> fruits) {
   for (Fruit fruit : fruits) {
      if (fruit.getName().equals(name)) {
         return Optional.of(fruit);
      }
   }
   return Optional.empty();
}

이 이 코드에서는, 「」의 가 검색됩니다. 이 코드에서는Fruit )fruits「 」 「 」 、 「 」

Optional<Fruit> found = find("lemon", fruits);
if (found.isPresent()) {
   Fruit fruit = found.get();
   String name = fruit.getName();
}

.map()연산자는 옵션 객체에 대해 계산을 수행하거나 값을 추출합니다. orElse()를 사용하면 결측값에 대한 폴백을 제공할 수 있습니다.

String nameOrNull = find("lemon", fruits)
    .map(f -> f.getName())
    .orElse("empty-name");

물론 null/empty 값 체크는 여전히 필요하지만 적어도 개발자는 값이 비어 있을 수 있고 확인하는 것을 잊어버릴 위험이 제한된다는 것을 알고 있습니다.

「」를 .Optional 있을 수 될 수 에만 반환됩니다.null(규약), 클라이언트코드가 단순한 오브젝트 반환값에 대한 늘체크를 포기할 수 있습니다...

입니다.Optional는 메서드 인수로도 사용할 수 있습니다.옵션 인수를 지정하는 것이 경우에 따라서는 5 또는 10의 오버로드 메서드보다 좋을 수 있습니다.

Optional는 다음과 같은 편리한 다른 방법을 제공합니다.orElse 및 「디폴트값의 사용」을 허가하는 것.ifPresent람다 표정과 잘 맞는 것 같아요

.NullPointerException과 (가져다닐 경우)가 OptionalJava Optional Objects에 대해 잘 설명합니다.

체크하는 오브젝트의 종류에 따라 apache commons lang 및 apache commons collections 의 Apache 커먼스의 클래스를 사용할 수 있습니다.

예:

String foo;
...
if( StringUtils.isBlank( foo ) ) {
   ///do something
}

또는 (확인해야 할 항목에 따라 다름):

String foo;
...
if( StringUtils.isEmpty( foo ) ) {
   ///do something
}

String Utils 클래스는 다수의 클래스 중 하나일 뿐이며, 커먼스에는 null safe 조작을 실행하는 좋은 클래스가 꽤 있습니다.

다음으로 아파치라이브러리(commons-lang-2.4.jar)를 포함할 때 JAVA에서 늘 발리데이션(null validation)을 사용하는 예를 나타냅니다.

public DOCUMENT read(String xml, ValidationEventHandler validationEventHandler) {
    Validate.notNull(validationEventHandler,"ValidationHandler not Injected");
    return read(new StringReader(xml), true, validationEventHandler);
}

스프링을 사용하는 경우 스프링도 패키지에 동일한 기능이 있습니다. 라이브러리(스프링-2.4.6.jar)를 참조하십시오.

spring(또는 springframework.util)에서 이 static classf를 사용하는 방법의 예.단언)

Assert.notNull(validationEventHandler,"ValidationHandler not Injected");
  • 오브젝트가 늘(또는 버그)이 아니라고 생각되는 경우 아사트를 사용합니다.
  • 메서드가 null 매개 변수를 허용하지 않는 경우 javadoc에서 null 매개 변수를 말하고 Assert를 사용합니다.

개체가 null일 수 있는 경우를 처리하려는 경우에만 != null 개체를 확인해야 합니다.

null/notnull 파라미터에 도움이 되는 새로운 주석을 Java7에 추가하는 제안이 있습니다.http://tech.puredanger.com/java7/ #jsr308

'이럴 수 없다'는 말이죠.신에자 매개 변수가 null인 경우 유용한 작업을 하고 있습니까?에 대한 는 안 됩니다)는후 조작을 해 주십시오. 이, 이, 이, 이, 이, 이, 이, 이, 이, 이, 이, 이, 이, 이, 이, 이, 이, 이, 이, 이, 이.그러면 이 코드를 무시하고 다음 명령을 허용하십시오.NullPointerException발신 , NPE , NPE 의미.IllegalArgumentException, 는, 그 외의 예기치 않은 하려고 하는 보다, 경우에 이 잘못되었는지 해 실패하게 .코드가 예기치 않은 다른 우발적인 로직을 실행하려고 하는 것이 아니라 결과적으로 애플리케이션이 실패하게 됩니다.

Null Object Pattern이 아닌 Null Object Pattern이 버그인 경우를 고려할 수 있습니다.

예외가 발생하면 스택트레이스를 조사하여 오류를 해결합니다.

경우에 따라서는 대칭 연산을 정의하는 파라미터로 동작하는 메서드가 있습니다.

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

수 것을 , 바꿀수 는 null로, null로, null로, null로, null로, null로, null로, null로, null로, null로, null로, null로, null로 바꿀 수 있습니다.할 때 foo.equals("bar"); 편이 "bar".equals(foo);.

Google 컬렉션 프레임워크는 Null Check를 달성할 수 있는 훌륭하고 우아한 방법을 제공합니다.

라이브러리 클래스에는 다음과 같은 방법이 있습니다.

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();

Null은 '문제'가 아닙니다.완전한 모델링 도구 세트의 필수 요소입니다.소프트웨어는 세상의 복잡함을 모델화하는 것을 목표로 하고 있으며, Null은 그 부담을 떠안고 있습니다.null은 Java 등에서 '데이터 없음' 또는 '수 없음'을 나타냅니다.따라서 이러한 목적에는 null을 사용하는 것이 적절합니다.나는 'Null object' 패턴을 선호하지 않는다; 나는 그것이 '가디언을 누가 지켜줄 것인가' 문제를 야기한다고 생각한다.
내 여자친구 이름이 뭐냐고 물어보면 여자친구가 없다고 말해줄게.Java 어을을을 null 을 java java java 。다른 방법으로는 의미 있는 예외를 발생시켜 바로 해결할 수 없는(또는 해결하기를 원하지 않는) 문제를 지적하고 스택의 상위 어딘가에 위임하여 데이터 액세스 오류를 다시 시도하거나 사용자에게 보고하는 방법이 있습니다.

  1. '알 수 없는 질문'의 경우 '알 수 없는 답변'을 제시합니다.(비즈니스 관점에서 이것이 올바른 경우에는 항상 안전합니다.)사용 전에 메서드 내에서 늘 인수를 1회 체크하면 여러 발신자가 콜 전에 늘 인수를 체크할 필요가 없어집니다.

    public Photo getPhotoOfThePerson(Person person) {
        if (person == null)
            return null;
        // Grabbing some resources or intensive calculation
        // using person object anyhow.
    }
    

    이전은 내 사진 라이브러리에서 존재하지 않는 여자친구의 사진을 가져오지 않는 정상적인 논리 흐름으로 이어집니다.

    getPhotoOfThePerson(me.getGirlfriend())
    

    또한 새로운 Java API에도 적합합니다(앞으로)

    getPhotoByName(me.getGirlfriend()?.getName())
    

    DB에 저장된 사진을 찾지 않는 것이 '정상적인 비즈니스 흐름'이지만, 다른 경우에는 다음과 같은 쌍을 사용하곤 했습니다.

    public static MyEnum parseMyEnum(String value); // throws IllegalArgumentException
    public static MyEnum parseMyEnumOrNull(String value);
    

    타이핑하는 마세요.<alt> + <shift> + <j>(Eclipse) javadoc API를 사용합니다.이것은 설명서를 읽지 않는 사람들을 제외하고는 충분할 것입니다.

    /**
     * @return photo or null
     */
    

    또는

    /**
     * @return photo, never null
     */
    
  2. 이는 다소 이론적인 경우이며 대부분의 경우 java null safe API(10년 후에 출시되는 경우)를 선호해야 하지만의 서브클래스입니다.따라서 이것은 의 한 형태이다.Throwable적절한 어플리케이션에서 포착하고 싶은 조건(adoc)을 나타냅니다.예외의 첫 번째 장점을 사용하고 오류 처리 코드를 (Java의 작성자에 따르면) '일반' 코드와 분리하는 것은 나로서도 적절하다.NullPointerException.

    public Photo getGirlfriendPhoto() {
        try {
            return appContext.getPhotoDataSource().getPhotoByName(me.getGirlfriend().getName());
        } catch (NullPointerException e) {
            return null;
        }
    }
    

    다음과 같은 질문이 발생할 수 있습니다.

    Q. 의 getPhotoDataSource() nullreturns null?는?
    A. 비즈니스 논리에 달려 있습니다.사진첩을 찾지 못하면 사진을 보여주지 않겠습니다.app Context가 초기화되지 않으면 어떻게 됩니까?이 방법의 비즈니스 논리는 이를 뒷받침한다.같은 논리가 예외를 두는 것보다 더 엄격해야 할 경우 비즈니스 논리의 일부이며 null에 대한 명시적 체크를 사용해야 합니다(케이스 3).새로운 Java Null-safe API는 프로그래머 오류 발생 시 무엇을 의미하고 무엇을 의미하지 않는지 선택적으로 지정하기 위해 여기에 더 적합합니다.

    Q. 중복 코드가 실행되어 불필요한 리소스가 확보될 수 있습니다.
    A. 다음과 같은 경우 발생할 수 있습니다.getPhotoByName()데이터베이스 연결을 열려고 할 때PreparedStatement마지막으로 사용자 이름을 SQL 매개 변수로 사용합니다. 수 없는 질문에 대한 접근법은 알 수 없는 답을 제공합니다(사례 1) 여기서 작동합니다.리소스를 가져오기 전에 매개 변수를 확인하고 필요에 따라 '알 수 없는' 결과를 반환해야 합니다.

    Q. 이 접근법에는 트라이 클로징 오픈으로 인한 퍼포먼스 저하가 있습니다.
    A. 소프트웨어는 먼저 쉽게 이해하고 수정할 수 있어야 합니다.그 후에, 필요한 경우에만 퍼포먼스를 생각할 수 있었습니다!필요한 장소! (출처 등)

    PS. 이 접근방식은 '일반' 코드 원칙과 다른 에러 처리 코드를 사용하는 것이 타당하기 때문에 합리적으로 사용할 수 있습니다.다음 예를 생각해 보겠습니다.

    public SomeValue calculateSomeValueUsingSophisticatedLogic(Predicate predicate) {
        try {
            Result1 result1 = performSomeCalculation(predicate);
            Result2 result2 = performSomeOtherCalculation(result1.getSomeProperty());
            Result3 result3 = performThirdCalculation(result2.getSomeProperty());
            Result4 result4 = performLastCalculation(result3.getSomeProperty());
            return result4.getSomeProperty();
        } catch (NullPointerException e) {
            return null;
        }
    }
    
    public SomeValue calculateSomeValueUsingSophisticatedLogic(Predicate predicate) {
        SomeValue result = null;
        if (predicate != null) {
            Result1 result1 = performSomeCalculation(predicate);
            if (result1 != null && result1.getSomeProperty() != null) {
                Result2 result2 = performSomeOtherCalculation(result1.getSomeProperty());
                if (result2 != null && result2.getSomeProperty() != null) {
                    Result3 result3 = performThirdCalculation(result2.getSomeProperty());
                    if (result3 != null && result3.getSomeProperty() != null) {
                        Result4 result4 = performLastCalculation(result3.getSomeProperty());
                        if (result4 != null) {
                            result = result4.getSomeProperty();
                        }
                    }
                }
            }
        }
        return result;
    }
    

    PPS. 다운투표가 빠른 분(매뉴얼을 읽는 속도가 빠른 분)을 위해 저는 지금까지 Null-pointer exception(NPE; 늘포인트 예외)을 포착한 적이 없습니다.그러나 이 가능성은 Java 크리에이터에 의해 의도적으로 설계되었다. 왜냐하면 NPE는 다음 서브클래스의Exception자바 역사상 전례가 있습니다.ThreadDeath는 입니다.Error실제로 어플리케이션 오류가 아니라 단순히 잡힐 의도가 없었기 때문입니다!NPE는 어느 정도의 NPE로Error보다ThreadDeath하지만 그렇지 않다.

  3. 비즈니스 로직이 시사하는 경우에만 '데이터 없음'을 확인합니다.

    public void updatePersonPhoneNumber(Long personId, String phoneNumber) {
        if (personId == null)
            return;
        DataSource dataSource = appContext.getStuffDataSource();
        Person person = dataSource.getPersonById(personId);
        if (person != null) {
            person.setPhoneNumber(phoneNumber);
            dataSource.updatePerson(person);
        } else {
            Person = new Person(personId);
            person.setPhoneNumber(phoneNumber);
            dataSource.insertPerson(person);
        }
    }
    

    그리고.

    public void updatePersonPhoneNumber(Long personId, String phoneNumber) {
        if (personId == null)
            return;
        DataSource dataSource = appContext.getStuffDataSource();
        Person person = dataSource.getPersonById(personId);
        if (person == null)
            throw new SomeReasonableUserException("What are you thinking about ???");
        person.setPhoneNumber(phoneNumber);
        dataSource.updatePerson(person);
    }
    

    appContext 또는 dataSource가 초기화되지 않은 경우 처리되지 않은 런타임 NullPointer예외는 현재 스레드를 중지하고 Thread.defaultUncaughtExceptionHandler에 의해 처리됩니다(마음에 드는 로거 또는 기타 알림 메커니즘을 정의하고 사용할 수 있습니다).설정하지 않으면 ThreadGroup#uncatchedException은 스택 트레이스를 시스템오류로 출력합니다.어플리케이션 에러 로그를 감시하고 처리되지 않은 각 예외(실제로 어플리케이션 에러)에 대해 Jira 문제를 열어야 합니다.프로그래머는 초기화 관련 버그를 수정해야 합니다.

자바 7은 새로운 기능이 탑재되어 있습니다.java.util.Objects가 있는 유틸리티 클래스requireNonNull()방법.이게 하는 일이라곤...NullPointerException인수가 null인 경우 코드를 약간 삭제합니다.예:

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

이 메서드는 컨스트럭터에서 할당 직전에 체크할 때 가장 유용합니다.이 메서드를 사용할 때마다 3줄의 코드를 저장할 수 있습니다.

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

된다

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

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

  • Objective-C 에서는, 다음과 같은 방법으로 메서드를 호출할 수 있습니다.nil그리고 아무 일도 일어나지 않을 것이다.이로 인해 대부분의 null 체크는 불필요하지만 오류를 진단하기가 훨씬 어려워질 수 있습니다.
  • Java에서 파생된 언어인 Nice에는 모든 유형의 두 가지 버전이 있습니다. 잠재 Null 버전과 Null 버전이 아닌 버전입니다.null이 아닌 유형에서만 메서드를 호출할 수 있습니다.null일 가능성이 있는 유형은 null에 대한 명시적 체크를 통해 null이 아닌 유형으로 변환할 수 있습니다.이를 통해 null 체크가 필요한 위치와 필요하지 않은 위치를 훨씬 쉽게 알 수 있습니다.

Java에서 흔히 볼 수 있는 "문제"입니다.

우선, 이것에 대한 제 생각은:

NULL이 유효한 값이 아닌 NULL이 통과되었을 때 무언가를 먹는 것은 나쁘다고 생각합니다.어떤 에러로 메서드를 종료하지 않는 경우는, 메서드에 아무런 문제가 없는 것을 의미합니다.이것은 사실이 아닙니다.그리고 이 경우 null을 반환할 수 있으며, 수신 방식에서는 null을 다시 확인해도 종료되지 않고 "if != null" 등으로 끝납니다.

따라서 IMHO, null은 더 이상의 실행을 방해하는 중대한 오류여야 합니다(즉, null은 유효한 값이 아닙니다).

이 문제를 해결하는 방법은 다음과 같습니다.

첫째, 저는 이 관례를 따릅니다.

  1. 모든 공개 메서드/API는 항상 해당 인수의 null을 확인합니다.
  2. 모든 개인 메서드는 제어된 메서드이기 때문에 null을 검사하지 않습니다(위에서 처리되지 않은 경우 nullpointer 예외와 함께 die 상태로 둡니다).
  3. null을 체크하지 않는 다른 방법은 유틸리티 방식뿐입니다.공용이지만 어떤 이유로 전화를 걸면 어떤 파라미터를 전달하는지 알 수 있습니다.이건 물을 공급하지 않고 주전자에 물을 끓이려는 것과 같아요.

마지막으로 코드에서 퍼블릭 메서드의 첫 번째 행은 다음과 같습니다.

ValidationUtils.getNullValidator().addParam(plans, "plans").addParam(persons, "persons").validate();

체크할 파라미터를 추가할 수 있도록 addParam()은 self를 반환합니다.

방법validate()체크를 던지다ValidationException파라미터 중 하나가 null인 경우(체크박스를 켜거나 끄거나 하는 것은 디자인/맛의 문제일 뿐이지만)ValidationException체크되어 있습니다).

void validate() throws ValidationException;

예를 들어 "plans"가 null인 경우 메시지에는 다음 텍스트가 포함됩니다.

"매개 변수 [plans]대해 잘못된 인수 값 null이 발견되었습니다."

보시는 바와 같이 사용자 메시지에 addParam() 메서드(문자열)의 두 번째 값이 필요합니다.이는 리플렉션(어차피 이 투고의 대상이 아님)을 사용해도 전달된 변수 이름을 쉽게 검출할 수 없기 때문입니다.

네, 이 행을 벗어나면 null 값이 발생하지 않으므로 이러한 개체에 대해 메서드를 안전하게 호출할 수 있습니다.

이렇게 하면 코드가 깨끗하고 유지보수가 용이하며 읽기 쉽습니다.

이 질문을 하는 것은 오류 처리 전략에 관심이 있다는 것을 나타냅니다.오류 처리 방법과 장소는 아키텍처에 널리 퍼져 있는 문제입니다.여기에는 몇 가지 방법이 있습니다.

내가 가장 좋아하는 것: 예외는 '메인 루프'에서 또는 적절한 책임을 지고 다른 기능에서 이를 포착할 수 있도록 한다.에러 상태를 확인하고 적절히 대처하는 것은, 전문적 책임이라고 할 수 있습니다.

Aspect Oriented Programming도 꼭 봐주세요.삽입하는 방법이 깔끔합니다.if( o == null ) handleNull()바이트 코드에 입력합니다.

를 사용하는 것 외에assert다음 항목을 사용할 수 있습니다.

if (someobject == null) {
    // Handle null here then move on.
}

이것은 다음보다 약간 낫다.

if (someobject != null) {
    .....
    .....



    .....
}

그냥 null은 절대 쓰지 마세요.허락하지 마세요.

클래스에서는 대부분의 필드 및 로컬 변수가 null이 아닌 기본값을 가지고 있으며, 코드 곳곳에 계약문(항상 온라인 어설트)을 추가하여 이 명령어가 적용되도록 합니다(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가 아니라 이유를 알 수 있습니다.

구글에 의해 매우 유용한 핵심 라이브러리인 Guava는 null을 피하기 위해 멋지고 유용한 API를 가지고 있습니다.Using Andoiding Null 설명에 큰 도움이 되었습니다.

Wiki에서 설명한 바와 같이:

Optional<T>는 nullable T 참조를 null 이외의 값으로 대체하는 방법입니다.옵션에는 Null이 아닌 T 참조가 포함되거나(이 경우 참조가 "존재"라고 함), 또는 아무것도 포함되지 않을 수 있습니다(이 경우 참조가 "부재"라고 함).그것은 결코 "무효를 포함한다"고 말하지 않는다.

사용방법:

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

이것은 모든 Java 개발자에게 매우 일반적인 문제입니다.따라서 Java 8에서는 코드를 복잡하게 만들지 않고 이러한 문제를 해결할 수 있는 공식적인 지원이 있습니다.

자바 8을 도입했다.java.util.Optional<T>는 null이 아닌 값이 안될 수도 있다. 그것은 있는 컨테이너입니다.자바 8보다 안전한 방법이 값 일부의 경우에서가 null이 될 수 있는 개체 처리하는 기회를 주었습니다.그것은 해스켈과 스칼라의 아이디어로부터 영감을 받았다.

한마디로 말해서, 옵션 클래스 메서드를 명시적으로 어디 값이나 결석한 선물은 사건들이 해결을 포함합니다.하지만, 이점을 null참조와 비교해 Optional< 있다.T>클래스 힘이 가치 존재하지 않는 사건에 대한 생각해야 한다.그 결과,은 의도하지 않은 null포인터 예외를 막을 수 있다.

위 예에서 우리는 여러 가전 제품은 집에서 사용할 수에 대한 핸들을 반환하는 집 서비스 공장을 가지고 있습니다.하지만 이러한 서비스할 수도 혹은available/functional지 않을 수도 있다. 그것은 NullPointer을 야기할 수도 있다는 것을 의미한다.예외.대신 null을 추가하는.if어떤 서비스를 이용하기 전 Condition의 Optional&lt에 들어가 버려;.Service&gt을 말한다.

OPTION< 독자 WRAPPING.T>

의 공장에서 서비스에 대한 참조를 가져오는 방법을 고려해 보자.대신에 서비스 참조할 옵션으로 싸두도 록 하자.그것은 API사용자가 반환된 서비스일 수도 아닐 수available/functional도 알다시피, 수비적으로 사용할 수 있습니다.

public Optional<Service> getRefrigertorControl() {
      Service s = new  RefrigeratorService();
       //...
      return Optional.ofNullable(s);
   }

보시다시피.Optional.ofNullable()그럼 참조를 쉽게 래핑할 수 있습니다.Optional의 참조를 취득하는 다른 방법도 있습니다.Optional.empty()&Optional.of()하나는 null을 반환하는 대신 빈 개체를 반환하는 것이고 다른 하나는 null이 아닌 개체를 랩하는 것입니다.

그럼 정확히 어떻게 무효체크를 회피할 수 있을까요?

참조 오브젝트를 랩하면 [Optional]에서는 NPE를 사용하지 않고 랩된 참조에서 메서드를 호출할 수 있는 편리한 메서드가 많이 제공됩니다.

Optional ref = homeServices.getRefrigertorControl();
ref.ifPresent(HomeServices::switchItOn);

선택 사항. null이 아닌 값인 경우 참조와 함께 지정된 컨슈머를 호출하는 경우.그렇지 않으면 아무 일도 일어나지 않습니다.

@FunctionalInterface
public interface Consumer<T>

단일 입력 인수를 수락하고 결과를 반환하지 않는 작업을 나타냅니다.대부분의 다른 기능 인터페이스와 달리 컨슈머는 부작용을 통해 작동할 것으로 예상된다.그것은 매우 깨끗하고 이해하기 쉽다.위의 코드 예에서는HomeService.switchOn(Service)는 옵션 보류 참조가 null이 아닌 경우 호출됩니다.

null 조건을 체크하기 위해 3진 연산자를 자주 사용하고 대체 값 또는 기본값을 반환합니다.옵션에서는 null을 체크하지 않고 동일한 상태를 처리할 수 있습니다.Optional.orElse(defaultObj)는 Optional 값이 null인 경우 defaultObj를 반환합니다.샘플 코드에 이것을 사용합니다.

public static Optional<HomeServices> get() {
    service = Optional.of(service.orElse(new HomeServices()));
    return service;
}

이제 HomeServices.get()도 같은 작업을 수행하지만 더 나은 방식으로 수행합니다.서비스가 이미 초기화되지 않았는지 확인합니다.동일한 경우 동일한 서비스를 반환하거나 새 서비스를 만듭니다.옵션<T>.orElse(T)를 사용하면 기본값이 반환됩니다.

마지막으로 NPE와 null 체크프리 코드를 나타냅니다.

import java.util.Optional;
public class HomeServices {
    private static final int NOW = 0;
    private static Optional<HomeServices> service;

public static Optional<HomeServices> get() {
    service = Optional.of(service.orElse(new HomeServices()));
    return service;
}

public Optional<Service> getRefrigertorControl() {
    Service s = new  RefrigeratorService();
    //...
    return Optional.ofNullable(s);
}

public static void main(String[] args) {
    /* Get Home Services handle */
    Optional<HomeServices> homeServices = HomeServices.get();
    if(homeServices != null) {
        Optional<Service> refrigertorControl = homeServices.get().getRefrigertorControl();
        refrigertorControl.ifPresent(HomeServices::switchItOn);
    }
}

public static void switchItOn(Service s){
         //...
    }
}

완전한 투고는 NPE와 Null 체크프리 코드입니다 정말요?

난 냇 프라이스의 기사를 좋아해다음은 링크입니다.

기사에는 Java Maybe Type의 Git 저장소에 대한 링크도 있습니다.재미있지만 그것만으로는 체크코드 부피를 줄일 수 없다고 생각합니다.인터넷에서 조사해 본 결과, 주로 세심한 디자인으로 != 늘 코드 블러트를 줄일 수 있다고 생각합니다.

제가 한번 해봤는데NullObjectPattern하지만 내게는 항상 최선의 방법은 아니다.때때로 "무조치"가 적절하지 않을 때가 있다.

NullPointerException런타임 예외는 개발자 오류임을 의미하며 충분한 경험을 바탕으로 오류 위치를 정확하게 알 수 있습니다.

자, 이제 답을 제시하겠습니다.

모든 Atribut과 Atribute의 Accessor를 가능한 한 비공개로 하거나 클라이언트에 공개하지 않도록 합니다.물론 생성자에 인수 값을 지정할 수 있지만 범위를 줄이면 클라이언트 클래스가 잘못된 값을 전달하지 않습니다.값을 수정해야 하는 경우 언제든지 새 값을 생성할 수 있습니다.object. 컨스트럭터의 값은 1회만 체크하고 나머지 메서드에서는 값이 null이 아님을 거의 확인할 수 있습니다.

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

바이트!

Java 8 이후로는 클래스를 사용하는 것이 가장 좋습니다.

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

이것은 특히 null 값을 가질 수 있는 긴 체인에 편리합니다.예:

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

null에 예외를 발생시키는 예:

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

Java 7은 Null이 아닌지를 확인해야 할 때 편리할 수 있는 방법을 도입했습니다.예:

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

좀 더 일반적으로 대답해도 될까요?

보통 이 문제는 메서드가 예기치 않은 방법으로 파라미터를 취득할 때 발생합니다(부정한 메서드 호출은 프로그래머의 장애입니다).예를 들어 오브젝트를 얻을 것으로 예상되지만 null을 얻을 수 없습니다.적어도 1개의 문자가 포함된 문자열을 얻을 것으로 예상되지만 빈 문자열이 됩니다.

따라서 다음 항목에는 차이가 없습니다.

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과 같은 핵심 Java 주석을 사용합니다.Null 또는 Hibernate Validator와 같은 고급 라이브러리를 사용하지 마십시오.

샘플:

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

이제 입력 파라미터를 확인할 필요 없이 메서드의 핵심 기능을 안전하게 개발할 수 있습니다.이러한 기능은 예기치 않은 파라미터로부터 메서드를 보호합니다.

한 걸음 더 나아가 어플리케이션에서 유효한 pojo만 생성할 수 있는지 확인할 수 있습니다.(동면 상태의 검증 사이트에서 샘플)

public class Car {

   @NotNull
   private String manufacturer;

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

   @Min(2)
   private int seatCount;

   // ...
}

모든 상황에서 null 객체를 사용하라는 답변은 무시합니다.이러한 패턴은 계약을 파기하고 문제를 해결하는 대신 점점 더 깊이 파고들 수 있습니다.부적절하게 사용하면 향후 유지보수가 필요한 보일러 플레이트 코드 더미가 생성된다는 것은 말할 것도 없습니다.

실제로는 메서드에서 반환된 것이 늘일 수 있고 발신자 코드가 이를 결정해야 할 경우 상태를 보증하는 이전 콜이 존재해야 합니다.

또, 이 늘 오브젝트 패턴은, 부주의하게 사용하면 메모리가 부족하게 됩니다.이를 위해 NullObject의 인스턴스는 소유자 간에 공유되어야 하며 이들 각각에 대해 unigue 인스턴스가 되어서는 안 됩니다.

또한 유형이 스칼라(벡터, 매트릭스, 복소수 및 POD(Plain Old Data) 객체)가 아닌 수학적 엔티티와 같은 원시 유형 표현인 경우에는 이 패턴을 사용하지 않는 것이 좋습니다.후자의 경우 getter 메서드를 호출하여 임의의 결과를 얻을 수 있습니다.예를 들어 NullPerson.getName() 메서드는 무엇을 반환해야 합니까?

부조리한 결과를 피하기 위해 그런 경우를 고려해 볼 가치가 있다.

  1. 변수를 null로 초기화하지 마십시오.
  2. (1)이 불가능한 경우 모든 컬렉션과 어레이를 빈 컬렉션/어레이로 초기화합니다.

사용자 고유의 코드로 이 작업을 수행하면 != null 검사를 피할 수 있습니다.

대부분의 경우 null 체크는 컬렉션이나 어레이에 대한 루프를 보호하는 것처럼 보이므로 빈 상태로 초기화하면 null 체크가 필요하지 않습니다.

// Bad
ArrayList<String> lemmings;
String[] names;

void checkLemmings() {
    if (lemmings != null) for(lemming: lemmings) {
        // do something
    }
}



// Good
ArrayList<String> lemmings = new ArrayList<String>();
String[] names = {};

void checkLemmings() {
    for(lemming: lemmings) {
        // do something
    }
}

여기에는 약간의 오버헤드가 있지만 더 깔끔한 코드와 더 적은 Null Pointer를 위해 가치가 있습니다.예외입니다.

이것은 대부분의 개발자에게서 발생하는 가장 일반적인 오류입니다.

이 문제를 해결할 방법은 여러 가지가 있습니다.

접근법 1:

org.apache.commons.lang.Validate //using apache framework

not Null(개체 객체, 문자열 메시지)

접근법 2:

if(someObject!=null){ // simply checking against null
}

접근법 3:

@isNull @Nullable  // using annotation based validation

접근법 4:

// by writing static method and calling it across whereever we needed to check the validation

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

Java 8은 java.util 패키지에 새로운 클래스 Optional을 도입했습니다.

Java 8의 장점(옵션):

1) null 체크는 필요 없습니다.
2) Null Pointer는 없습니다.런타임의 예외입니다.
3) 깔끔하고 깔끔한 API를 개발할 수 있습니다.

선택 사항 - null이 아닌 값을 포함할 수도 있고 포함하지 않을 수도 있는 컨테이너 개체입니다.값이 존재하는 경우 isPresent()는 true를 반환하고 get()은 값을 반환합니다.

상세한 것에 대하여는, https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html 를 참조해 주세요.

언급URL : https://stackoverflow.com/questions/271526/avoiding-nullpointerexception-in-java

반응형