[Java] 回避する!= null文



Answers

JetBrains IntelliJ IDEA 、Eclipse、NetbeansのようなJava IDE、またはfindbugsのようなツールを使用する(または使用する予定がある)場合、注釈を使用してこの問題を解決できます。

基本的に、あなたは@Nullable@NotNullます。

次のように、メソッドとパラメータで使用できます。

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

または

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

2番目の例はコンパイルされません(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以降では、他の@Nullable @NotNull実装のサポートが追加されました。

ブログ投稿を見るもっと柔軟で設定可能な@ Nullable / @ NotNullアノテーション

Question

私はobject != nullを使用object != null NullPointerExceptionを避けるために多くのobject != null

これには良い選択肢がありますか?

例えば:

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

これにより、オブジェクトがnullかどうかが不明な場合にNullPointerExceptionを回避できます。

受け入れられた回答は古いかもしれないことに注意してhttps://.com/a/2386013/12943 。最近のアプローチについてはhttps://.com/a/2386013/12943を参照してhttps://.com/a/2386013/12943 。




Java 7には、 requireNonNull()メソッドがある新しいjava.util.Objectsユーティリティクラスがあります。 引数がnullの場合はNullPointerExceptionがスローされますが、コードが少しクリアされます。 例:

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

このメソッドは、コンストラクタ内の代入の直前にcheckingのに最も便利です。コンストラクタを使用するたびに、次の3行のコードを保存できます。

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

〜になる

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



このような状況の場合のみ - 文字列比較の前にnullをチェックしないようにする:

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

fooが存在しない場合、 NullPointerExceptionします。

このようにStringを比較すると、それを避けることができます:

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



  1. Never initialise variables to null.
  2. If (1) is not possible, initialise all collections and arrays to empty collections/arrays.

Doing this in your own code and you can avoid != null checks.

Most of the time null checks seem to guard loops over collections or arrays, so just initialise them empty, you won't need any null checks.

// 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
    }
}

There is a tiny overhead in this, but it's worth it for cleaner code and less NullPointerExceptions.




This is a very common problem for every Java developer. So there is official support in Java 8 to address these issues without cluttered code.

Java 8 has introduced java.util.Optional<T> . It is a container that may or may not hold a non-null value. Java 8 has given a safer way to handle an object whose value may be null in some of the cases. It is inspired from the ideas of Haskell and Scala .

In a nutshell, the Optional class includes methods to explicitly deal with the cases where a value is present or absent. However, the advantage compared to null references is that the Optional<T> class forces you to think about the case when the value is not present. As a consequence, you can prevent unintended null pointer exceptions.

In above example we have a home service factory that returns a handle to multiple appliances available in the home. But these services may or may not be available/functional; it means it may result in a NullPointerException. Instead of adding a null if condition before using any service, let's wrap it in to Optional<Service>.

WRAPPING TO OPTION<T>

Let's consider a method to get a reference of a service from a factory. Instead of returning the service reference, wrap it with Optional. It lets the API user know that the returned service may or may not available/functional, use defensively

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

As you see Optional.ofNullable() provides an easy way to get the reference wrapped. There are another ways to get the reference of Optional, either Optional.empty() & Optional.of() . One for returning an empty object instead of retuning null and the other to wrap a non-nullable object, respectively.

SO HOW EXACTLY IT HELPS TO AVOID A NULL CHECK?

Once you have wrapped a reference object, Optional provides many useful methods to invoke methods on a wrapped reference without NPE.

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

Optional.ifPresent invokes the given Consumer with a reference if it is a non-null value. Otherwise, it does nothing.

@FunctionalInterface
public interface Consumer<T>

Represents an operation that accepts a single input argument and returns no result. Unlike most other functional interfaces, Consumer is expected to operate via side-effects. It is so clean and easy to understand. In the above code example, HomeService.switchOn(Service) gets invoked if the Optional holding reference is non-null.

We use the ternary operator very often for checking null condition and return an alternative value or default value. Optional provides another way to handle the same condition without checking null. Optional.orElse(defaultObj) returns defaultObj if the Optional has a null value. Let's use this in our sample code:

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

Now HomeServices.get() does same thing, but in a better way. It checks whether the service is already initialized of not. If it is then return the same or create a new New service. Optional<T>.orElse(T) helps to return a default value.

Finally, here is our NPE as well as null check-free code:

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){
         //...
    }
}

The complete post is NPE as well as Null check-free code … Really?




I highly disregard answers that suggest using the null objects in every situation. This pattern may break the contract and bury problems deeper and deeper instead of solving them, not mentioning that used inappropriately will create another pile of boilerplate code that will require future maintenance.

In reality if something returned from a method can be null and the calling code has to make decision upon that, there should an earlier call that ensures the state.

Also keep in mind, that null object pattern will be memory hungry if used without care. For this - the instance of a NullObject should be shared between owners, and not be an unigue instance for each of these.

Also I would not recommend using this pattern where the type is meant to be a primitive type representation - like mathematical entities, that are not scalars: vectors, matrices, complex numbers and POD(Plain Old Data) objects, which are meant to hold state in form of Java built-in types. In the latter case you would end up calling getter methods with arbitrary results. For example what should a NullPerson.getName() method return?

It's worth considering such cases in order to avoid absurd results.




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



私は "失敗高速"のファンです。 自分自身に尋ねます - パラメータがnullの場合に役立つ何かをしていますか? その場合にコードが行うべきことについて明確な答えがない場合、つまり、最初はnullであってはならず、無視してNullPointerExceptionをスローすることができます。 呼び出し側のコードは、NPEをIllegalArgumentExceptionと同じように理解しますが、予期せぬその他の不測の事態を実行しようとするコードではなく、NPEがスローされた場合に、開発者がデバッグして何がうまくいかないかを理解することが容易になりますロジック - 最終的にはアプリケーションが失敗することになります。




あなたがチェックしているオブジェクトの種類に応じて、apacheコモンズのいくつかのクラスを使うことができるかもしれません: apache commons langapache commons collections

例:

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

または(あなたがチェックする必要があるものに応じて):

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

StringUtilsクラスは多くのうちの1つです。 ヌルの安全な操作を行うコモンズにはかなりのクラスがあります。

ここでは、apacheライブラリ(commons-lang-2.4.jar)をインクルードするときに、Javaでnull valallationを使用する方法の例を示します。

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

また、Springを使用している場合、Springもパッケージと同じ機能を持ちます(library(spring-2.4.6.jar)

この静的クラスをSpring(org.springframework.util.Assert)から使用する方法の例

Assert.notNull(validationEventHandler,"ValidationHandler not Injected");



Googleコレクションフレームワークは、ヌルチェックを達成するうまいエレガントな方法を提供します。

次のようなライブラリクラスにメソッドがあります:

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



うわー、私はNullObject patternを推奨する57の異なる方法があるときに別の答えを追加することはほとんど嫌いですが、この質問に興味がある人は、Java 7のテーブルに「null」を追加する提案があることを知りたいかもしれないと思います「セーフ・ハンドリング」 - 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セーフな演算子のproposedProject Coinに提出されました 構文は上記の例とは少し異なりますが、同じ考え方です。

更新: null安全な演算子の提案は、Project Coinには入れませんでした。 したがって、Java 7ではこの構文は見られません。




Just don't ever use null. Don't allow it.

In my classes, most fields and local variables have non-null default values, and I add contract statements (always-on asserts) everywhere in the code to make sure this is being enforced (since it's more succinct, and more expressive than letting it come up as an NPE and then having to resolve the line number, etc.).

Once I adopted this practice, I noticed that the problems seemed to fix themselves. You'd catch things much earlier in the development process just by accident and realize you had a weak spot.. and more importantly.. it helps encapsulate different modules' concerns, different modules can 'trust' each other, and no more littering the code with if = null else constructs!

This is defensive programming and results in much cleaner code in the long run. Always sanitize the data, eg here by enforcing rigid standards, and the problems go away.

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; }
}

The contracts are like mini-unit tests which are always running, even in production, and when things fail, you know why, rather than a random NPE you have to somehow figure out.




Ultimately, the only way to completely solve this problem is by using a different programming language:

  • In Objective-C, you can do the equivalent of invoking a method on nil , and absolutely nothing will happen. This makes most null checks unnecessary, but it can make errors much harder to diagnose.
  • In Nice , a Java-derived language, there are two versions of all types: a potentially-null version and a not-null version. You can only invoke methods on not-null types. Potentially-null types can be converted to not-null types through explicit checking for null. This makes it much easier to know where null checks are necessary and where they aren't.



Asking that question points out that you may be interested in error handling strategies. Your team's architect should decide how to work errors. There are several ways to do this:

  1. allow the Exceptions to ripple through - catch them at the 'main loop' or in some other managing routine.

    • check for error conditions and handle them appropriately

Sure do have a look at Aspect Oriented Programming, too - they have neat ways to insert if( o == null ) handleNull() into your bytecode.




I've tried the NullObjectPattern but for me is not always the best way to go. There are sometimes when a "no action" is not appropiate.

NullPointerException is a Runtime exception that means it's developers fault and with enough experience it tells you exactly where is the error.

Now to the answer:

Try to make all your attributes and its accessors as private as possible or avoid to expose them to the clients at all. You can have the argument values in the constructor of course, but by reducing the scope you don't let the client class pass an invalid value. If you need to modify the values, you can always create a new object . You check the values in the constructor only once and in the rest of the methods you can be almost sure that the values are not null.

Of course, experience is the better way to understand and apply this suggestion.

Byte!




Links