火曜日にJavaが有効になります!変動を最小化

今日のトピックは、可変性と、値オブジェクトを不変にすることの利点についてです。これは非常に単純で、アプリケーションの他の多くの部分をより単純にすることができるので、これは良いトピックだと思います。なんて素晴らしい組み合わせでしょう!

不変オブジェクトの概念は単純で、一度作成すると変更できないオブジェクトです。Javaプラットフォームライブラリは、文字列、大きな10進数、大きな整数、ボックス化されたプリミティブ型などの不変クラスのいくつかの例を提供します。それでは、何かを不変にすることを選択するのはなぜですか?機能を削除することは悪いことではありませんか?興味深いことに、多くの場合そうなりますが、実際に何かを実行する機能を削除すると、他のことがはるかに簡単かつ安全になります。不変性の説明に入る前に、クラスを不変にする方法について説明しましょう。

  1. 状態を変更する方法を提供しないでください。通常、ミューテーターまたはセッターと呼ばれます。クラスを拡大できないようにする最も一般的な方法は、コースを採点することです。すべてのフィールドをfinalにします。内部状態を変更しないことを明確にします また、あるスレッドから別のスレッドに状態を渡すときにも役立ちます。すべてのフィールドを非公開にします。以下の他のガイドラインに従えば、Javaでも効果的に実行できる可能性があります。同じ理由で、このガイドに従ってください。変更可能な状態への排他的アクセスを確保する:不変オブジェクトがアクセサーを介して変更可能な状態を提供する場合、防御的なコピーを作成して、その内部状態を保護する必要があります。

例を見てみましょう:

@Getter
public final class ComplexNumber {
  private final double real;
  private final double imaginary;

  public ComplexNumber(double real, double imaginary) {
    this.real = real;
    this.imaginary = imaginary;
  }

  public ComplexNumber plus(ComplexNumber other) {
     return new ComplexNumber(this.real + other.real, this.imaginary + other.imaginary);
  }

  public ComplexNumber minus(ComplexNumber other) {
     return new ComplexNumber(this.real - other.real, this.imaginary - other.imaginary);
  }

  // ... other methods
}

それでは、この種の興味深いものをいくつか見てみましょう。最初に気付くのは、それを最終クラスと最終メンバー変数にする規則に従うことです。また、何かが欠けていることに気づくでしょう、変異体。おそらく最も興味深いのは、加算と減算の方法です。既存の状態を変更する代わりに、複素数の新しいインスタンスを返します。この機能的アプローチを最初に目にしたとき、奇妙に見えることがあります。これらのメソッドが動詞(プラス)ではなく前置詞(プラス)と呼ばれていることもわかります。必須ではありませんが、この単語の選択の違いは、クラスのユーザーが新しいオブジェクトを受信しようとしていることを理解するのに役立ちます。

ここで、不変性を使用する利点を探求し続けましょう。

  • 不変オブジェクトは単純です。オブジェクトは1つの状態にのみ存在できます。これにより、オブジェクトの処理が大幅に簡略化されます。不変オブジェクトは本質的にスレッドセーフです。スレッド間の状態を破棄する方法はありません。これまでのところ、不変オブジェクトはスレッドセーフを実現する最も簡単な方法です。不変オブジェクトは自由に共有できます。状態は変更できないため、不変オブジェクトの共有について心配する必要はありません。オブジェクトがウィジェットを表す場合、オブジェクトは将来もウィジェットを表します。つまり、防御的なコピーを作成する必要はありません。これにより、一般的に使用されるオブジェクトをキャッシュし、要求されるたびにそれらを返すことができます(おそらく静的ファクトリーを使用します)。これにより、オブジェクトの作成が高速化され、メモリの負荷が軽減されます。オブジェクトを自由に共有できるだけでなく、オブジェクトを内部で共有することもできます。これはニッチプロジェクトのように見えますが、非常に興味深いものです。状態は変更されないため、異なるオブジェクト間で内部状態を共有できます。この本の例は、大きな整数オブジェクトが正または負の数を表すかどうかを示す符号ビットを持つことです。オブジェクトを無効にする場合は、新しいオブジェクトを作成するだけで済みます。大きな整数は符号ビットを反転し、元のオブジェクトの残りの状態を参照します。

したがって、不変オブジェクトには多くの利点があります。不利な要因は何であり、どうすればそれらを軽減できますか。

オブジェクト内の何かを変更するには、新しいオブジェクトを作成する必要があります。特にオブジェクトが大きい場合は、状態を少しだけ変更するために多くの新しいオブジェクトを作成すると、コストがかかる可能性があります。状態を変更するステップが複数ある場合、コストが高くなる可能性のあるオブジェクトが多数作成されるため、状態が悪化します。

では、どうすればこの状況を緩和できるでしょうか。ユーザーがオブジェクトに対していくつかの一般的な操作を実行したい場合は、マルチステッププロセスを処理できます。これは、ユーザーが実行する操作の種類を事前に知っている場合に役立ちます。これを行わないとどうなりますか?このメソッドを使用する別のオプションは、ユーザーが変更を実行できる変更可能なコンパニオンクラスを作成し、それを使用して不変クラスを作成することです。例としては、文字列ビルダークラスと、文字列オブジェクトを効果的に作成する機能があります。

最後にいくつかのことについて話し合いましょう。

クラスをファイナライズする代わりに、静的ファクトリーを使用して不変オブジェクトを作成する代わりに、プライベートコンストラクターを作成することもできます。これにより、将来的にクラスのサブクラスを選択できるようになり、将来のパフォーマンス最適化のための選択肢が提供されます。

もう1つ覚えておかなければならないのは、上で述べたように、状態を変更することはできないが、状態を外部に向けるだけでは変更できないことです。これは、戻り値が一貫している限り、データを内部的にキャッシュできることを意味します。

いつものように、私はロンボクが私たちの目標を達成するのを助けることができることを述べたいと思います。不変オブジェクトも同じです。Lombokには、クラスに追加する@valueアノテーションが含まれ、クラスを最後にし、すべてのプライベートな最後のメンバーにする変数を作成し、セッターを生成せず、他の多くのボイラープレートアイテム(hashCode、 、ToString)。このアノテーションを追加するだけでは、魔法のようにクラスが不変になるわけではありませんが、クラスのボイラープレートを不変の互換性のある方法で処理することで、うまくいくでしょう。

最後のアイデアは、実行できない理由がないか、実行できない場合を除いて、常に不変オブジェクトを作成することです。オブジェクトを完全に不変にできなくても、できるだけ不変にする必要があります。

あります。不変オブジェクト。それらは物事をより単純にし、コードをより使いやすくします。

から:https://dev.to//kylec32/effective-java-tuesday-minimize-mutability-55db

元の記事を公開0件 ・いい ね0件 405回アクセス

おすすめ

転載: blog.csdn.net/cunxiedian8614/article/details/105690118