Try using it in your preferred language.

English

  • English
  • 汉语
  • Español
  • Bahasa Indonesia
  • Português
  • Русский
  • 日本語
  • 한국어
  • Deutsch
  • Français
  • Italiano
  • Türkçe
  • Tiếng Việt
  • ไทย
  • Polski
  • Nederlands
  • हिन्दी
  • Magyar
translation

これはAIが翻訳した投稿です。

제이온

[Effective Java] アイテム6. 不要なオブジェクト生成を避ける

言語を選択

  • 日本語
  • English
  • 汉语
  • Español
  • Bahasa Indonesia
  • Português
  • Русский
  • 한국어
  • Deutsch
  • Français
  • Italiano
  • Türkçe
  • Tiếng Việt
  • ไทย
  • Polski
  • Nederlands
  • हिन्दी
  • Magyar

durumis AIが要約した文章

  • newキーワードを使用して文字列またはBooleanインスタンスを作成することは、メモリ浪費であるため、リテラルで宣言するか、 Boolean.valueOf()メソッドを使用するのが最適です。
  • String.matches()メソッドは正規表現を使用するため、パフォーマンス上の問題が発生する可能性があり、Patternインスタンスをキャッシュして 再利用するのが最適です。
  • keySet()メソッドなど、ビューオブジェクトを返す場合は、防御的コピーを使用して新しいオブジェクトを返す方が安全です。

不要なオブジェクトを作成する場合

new String() の使用

String a = new String("hi");
String b = new String("hi");


文字列 a、b、c はいずれも "hi" という文字列を持つようになります。しかし、この3つの文字列が参照するアドレスはすべて異なるため、同じ データに対して別々のメモリを割り当てているという無駄が発生します。


Untitled


そのため、文字列を宣言する際には、new キーワードを使用するのではなく、リテラルで宣言する必要があります。


String a = "hi";
String b = "hi";


上記のソースコードは、1つのインスタンスのみを使用しています。さらに、この方法を使用すると、同じ JVM 内で "hi" 文字列リテラルを使用する すべてのコードが同じオブジェクトを再利用することを保証します。これは、Java の定数プールの特徴によるものです。


new Boolean() の使用

上記のコードは、文字列をパラメータとして受け取るコンストラクタを使用して、Boolean インスタンスを作成しています。Boolean は true または false のみが存在しますが、毎回インスタンスを作成することはメモリ浪費になります。そのため、Boolean.valueOf() という静的ファクトリメソッドを使用する方が良いでしょう。



String.matches() の使用

生成コストが高い場合は、キャッシュして再利用する方が良いですが、常に私たちが作成するオブジェクトのコストを知ることはできません。たとえば、与えられた文字列が 有効なローマ数字であるかどうかを確認するメソッドを作成したい場合は、次のように正規表現を使用するのが最も簡単です。


public static boolean isRomanNumeral(String s) {
    return s.matches("^(?=.)M*(C[MD]|D?C{0,3})(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$");


しかし、String.matches() はパフォーマンス的に問題のあるメソッドです。このメソッドが内部で作成する正規表現用の Pattern インスタンスは、一度使用したら破棄され、すぐにガベージコレクションの対象となります。この正規表現が繰り返し使用される頻度が 高くなるほど、同じ Pattern インスタンスが生成され、破棄されるコストが高くなります。そのため、Pattern インスタンスを事前にキャッシュしておき、 後で isRomanNumeral() メソッドが呼び出されるたびに、このインスタンスを再利用する方が良いでしょう。


public class RomanNumerals {

    private static final Pattern ROMAN = Pattern.compile(
        "^(?=.)M*(C[MD]|D?C{0,3})(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$");

    public static boolean isRomanNumeral(String s) {
        return ROMAN.matcher(s).matches();
    }


注意事項

上記のすべての例では、不要なオブジェクトをキャッシュする際に、すべて不変オブジェクトとして作成しました。これは、再利用しても安全にするためです。しかし、不変 オブジェクトとして再利用するという直感に反するケースがあります。


アダプター(ビュー)は、実際の作業はバックエンドのオブジェクトに委譲し、自身は第2のインターフェースとしての役割を果たすオブジェクトです。アダプターは、バックエンドのオブジェクトのみを 管理すればよいので、バックエンドのオブジェクト1つにつきアダプターを1つだけ作成すればよいのです。


たとえば、Map インターフェースの keySet() メソッドは、Map オブジェクト内のすべてのキーを含む Set ビューを返します。ユーザーは、 keySet() メソッドを呼び出すたびに、新しい Set インスタンスが作成されると考えるかもしれません。しかし、実際の JDK の実装を見ると、 毎回同じ可変 Set インスタンスが返されます。


これは、返される Set インスタンスは可変であっても、実行する機能はすべて同じであり、すべての Set インスタンスが Map インスタンスを代表しているためです。したがって、keySet() がビューオブジェクトを複数作成しても問題はありませんが、そうする必要も利点もありません。


public class UsingKeySet {

    public static void main(String[] args) {
        Map menu = new HashMap<>();
        menu.put("Burger", 8);
        menu.put("Pizza", 9);

        Set names1 = menu.keySet();
        Set names2 = menu.keySet();

        names1.remove("Burger");
        System.out.println(names1.size()); // 1
        System.out.println(names2.size()); // 1
    }


そのため、上記のように names1 インスタンスを変更すると、names2 インスタンスにも影響が及ぶことになります。


しかし、個人的には、keySet() メソッドの戻り値は、防御的コピーを使用して、毎回新しいオブジェクトを返す方法が正しいと考えています。 もし、keySet() メソッドから受け取った Set インスタンスが、他の場所でも使用されており、このインスタンスの状態を変更するコードがある場合、 現在使用している Set インスタンスと Map インスタンスの値について確信が持てなくなります。


また、keySet() を過度に頻繁に使用している環境でない限り、Set インターフェースが毎回生成されたとしても、パフォーマンスに致命的な影響を与えることはありません。むしろ、Set インターフェースを不変オブジェクトとして作成し、安定して保守管理を行う方が良いと考えています。


オートボクシング

オートボクシングは、プログラマーが基本型とラッパー型を混在して使用する場合に、自動的に相互に変換する技術です。しかし、オートボクシングは基本型とラッパー型の違いをぼかすだけで、完全に消してしまうわけではありません。


public static long sum() {
    Long sum = 0L;
    for (long i = 0; i <= Integer.MAX_VALUE; i++) {
        sum += i;
    }
    return sum;


ロジック上は問題ありませんが、パフォーマンス的に非常に非効率的なコードです。これは、sum の型と for 文内の i の型によるものです。


sum の型は Long 型で、i は long 型です。つまり、long 型の i は、繰り返し文を回って sum に加算されるたびに、 新しい Long インスタンスが作成されます。結果として、ラッパー型よりも基本型を使用し、意図しないオートボクシングが行われないように注意する必要があります。


誤解しないように

不要なオブジェクトの作成を避けるべきだというのは、単にオブジェクト作成のコストが大きいので避けるべきだという誤解をしてはいけません。


特に、最近の JVM では、不要に生成された小さなオブジェクトを生成および回収することは、それほど負担のかかる作業ではありません。そのため、データベース 接続など、コストのかかるオブジェクトでない限り、カスタムオブジェクトプールを作成しないようにしましょう。


さらに、防御的コピーが必要な状況でオブジェクトを再利用した場合の被害は、不要なオブジェクトを繰り返し生成した場合の被害よりもはるかに大きいということを覚えておきましょう。繰り返し生成の副作用は、コードの形式とパフォーマンスにのみ影響しますが、防御的コピーが失敗すると、バグとセキュリティ問題につながります。


出典

제이온
제이온
제이온
제이온
[Effective Java] アイテム 1. 静的ファクトリメソッドをコンストラクタよりも優先する 静的ファクトリメソッドは、コンストラクタの代わりにインスタンスを作成する柔軟で効率的な方法です。 名前を付けることができ、特定の条件に合致するインスタンスを返したり、キャッシュを使ってパフォーマンスを向上させることができます。 シングルトンパターンとは異なり、複数のタイプのインスタンスを作成して返したり、リフレクションを使わずに柔軟性を維持することができます。

2024年4月27日

[エフェクティブ・Java] アイテム 5. リソースを明示的に指定するのではなく、依存オブジェクトの注入を使用する クラスが外部リソースに依存する場合、シングルトンと静的ユーティリティクラスは使用しないことをお勧めします。依存オブジェクトの注入により、 クラスの柔軟性、再利用性、テスト容易性を向上させることができ、ファクトリメソッドパターンを活用すれば、より効率的な依存オブジェクトの 注入が可能になります。

2024年4月28日

[効果的なJava] アイテム 2. コンストラクタに多くのパラメータがある場合は、ビルダーを検討する 多くのパラメータを持つオブジェクトを作成する場合、ビルダーパターンを使用すると、コードをよりクリーンで読みやすく作成できます。必須のパラメータでビルダーオブジェクトを作成し、setterメソッドで選択パラメータを設定し、build()メソッドを呼び出してオブジェクトを完成させます。このパターンは、特に階層的に設計されたクラスと組み合わせて使用する場合に便利です。 ([効果的なJava]から抜粋)

2024年4月27日

[Javascript] オブジェクトの構造 (V8) JavaScriptのObjectは、V8エンジンでは、状態に応じて、構造体のように最適化されたFastモードと、ハッシュマップとして動作するDictionary モードに変換されます。Fastモードは、キーと値がほとんど固定された形式で高速ですが、新しいキーが追加されたり、要素を削除したりするなどの操作が行われた場合、 Dictionaryモードに切り替わり、速度が遅くなる可能性があります。
곽경직
곽경직
곽경직
곽경직
곽경직

2024年3月18日

Rustが並行性バグを防ぐ方法 Rustは、並行プログラミングの課題を解決する強力な言語です。 型システムと所有権モデルにより、スレッド間のデータの受け渡しと共有が安全になります。 Mutex、Channel、Atomicなどの内部可変性パターンを通じて、共有変数を定義し、安全に使用することができます。 Rustは並行性問題を積極的に解決し、大規模システム開発に広く活用されています。
곽경직
곽경직
곽경직
곽경직
곽경직

2024年3月28日

[非専攻、開発者として生き残る] 14. 新卒開発者がよく聞かれる技術面接内容まとめ 新卒開発者向けの技術面接準備ガイドです。メインメモリ領域、データ構造、RDBMSとNoSQL、手続き型とオブジェクト指向、 オーバーライドとオーバーロード、ページ置換アルゴリズム、プロセスとスレッド、OSI 7層、TCPとUDPなど、面接でよく登場する概念を 説明します。
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자

2024年4月3日

[Concurrency] Atomic Operation: メモリフェンスとメモリオーダリング このブログ投稿では、アトミック演算でのメモリの順序付けを考慮する方法と、Orderingオプションの重要性を説明します。Relaxed、 Acquire、Release、AcqRel、SecCstなど、さまざまなOrderingオプションの詳細と、各オプションの長所と短所、および使用 時の注意点について、例コードと共に詳しく説明します。
곽경직
곽경직
곽경직
곽경직
곽경직

2024年4月12日

概念的データモデリング 概念的データモデリングは、エンティティを分離し、エンティティ間の関係をERDで表現するプロセスです。エンティティは独立した情報単位であり、属性は エンティティが持つデータです。識別子はエンティティを一意に識別し、関係はエンティティ間の相互作用を表します。カーディナリティはエンティティ間の数値的 関係、オプション性はデータの必須性を示します。
제이의 블로그
제이의 블로그
제이의 블로그
제이의 블로그

2024年4月8日

[python]Python 基礎1 Python モジュールについて Python モジュールは、変数、関数、クラスなどをまとめたファイルで、他の人が作ったモジュールを使用したり、共通的に使用される変数、関数などをまとめて使用する場合に便利です。`import` キーワードを使用してモジュールを呼び出して使用することができますし、直接モジュールを作成して使用することもできます。
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자

2024年3月27日