19

重複の可能性:
静的変数が悪と見なされるのはなぜですか?

特に Android を使用している場合は、すべてのプログラムで静的変数を広範囲に使用する習慣があります。Intents を介して 10 個以上の値を送信するのが面倒な場合があるため、私はそれらを使用する傾向があります。したがって、それらを静的変数として宣言し、「ドット」演算子を使用して他のクラスで簡単にアクセスします。静的変数を使用するもう 1 つの理由は、アプリケーション全体で使用するユーティリティ クラスを作成する場合です。以下に示したコードのように、さまざまなアクティビティで変数を使用するのに役立ちます。

ユーティリティ.java

public class Utility {
public static Facebook fb;
public static AsyncFacebookRunner fbAsyncRunner;
public static String[] fbPermissions = {"email", "read_stream", "user_birthday"};
public static final String PREF_UTILITY_FILE_NAME = "PrefUtilityFile";
public static SharedPreferences prefs;
public static Editor editor;
public static String access_token;
public static long expires;
}

同様の質問をオンラインで検索し、これこれに出会いましたが、問題に対する最終的な回答は得られないようです。そして、ほとんどの場所で意見の対立が見られ、完全に混乱しています。

それは良いプログラミング方法ですか、それとも悪い方法ですか? 私はそれを使用する必要がありますか?

4

5 に答える 5

18

すべての静的フィールドを、受け渡しまたはシングルトンを作成できる「コンテキスト」オブジェクトに置き換えることができます。ほとんどすべての静的フィールドを削除することができます。これが良いアイデアかどうかはあなた次第ですが、インスタンス フィールドを使用するのがはるかに難しいとは思いません。

ところで:私はお勧めします

  • それらを使用するクラスまたはパッケージに静的フィールド/定数を配置する
  • 可能であれば、静的配列も不変として扱いますfinal

非静的コンテキストを使用できます

public class Context {
    public static final String PREF_UTILITY_FILE_NAME = "PrefUtilityFile";

    public Facebook fb;
    public AsyncFacebookRunner fbAsyncRunner;
    public String[] fbPermissions = {"email", "read_stream", "user_birthday"};
    public SharedPreferences prefs;
    public Editor editor;
    public String access_token;
    public long expires;
}

// pass to constructor as required
class UsesContext {
    final Context context;
    public UsesContext(Context context) {
        this.context = context;
    }

    public void method() {
        // can use context
    }
}

これにより、複数のコンテキストで単体テストを作成できます。

私が静的に残す唯一のものは定数です。

于 2012-09-19T10:39:32.950 に答える
7

定期的に使用し続ける場合は静的変数に賛成であり、それらを最終的にすると値は決して変わりません。

なぜ物事は困難な方法で行うのですか?

それが静的変数のすべてです。

基本的に、それらが行うことは、任意のコンテキスト (静的、プログラム フロー、外部) からアクセスできる汎用アクセス ポイントを提供することです。

あなたは基本的に正面玄関がここにあり、それは黄色であると述べています. 誰かが外から覗くと、黄色いドアが見えます。内側を歩いている誰かがドアを見て、それが黄色であることを確認します。部屋の誰かが廊下を見ると、廊下が黄色であることがわかります。

そして、赤く塗れば、誰の目にもはっきりと見えます。

また、プログラム全体を通して、同じ値を持つインスタンスが常に 1 つ存在します。これはメモリを節約します。

たとえば

class test {
public int ten = 10;
   public test() {
   }
}

new test()整数を作成するたびに、10 個の変数にメモリ空間が割り当てられます。したがって、10 個のテスト インスタンスがある場合、10 個の個別の整数がすべて同じ値を保持することになります。

これがあれば

class test {
public static int ten = 10;
   public test() {
   }
}

10 個のテスト インスタンスがある場合、整数インスタンス 10は1 つだけになります。これにより、メモリ割り当て、ガベージ コレクションが節約されます。変更されない永続的なリスト/変数に対してのみこれをアドバイスしますが、無防備にメモリに保持する余裕があります。すべての変数でこれを行わないでください。これは、何度も再利用する画像などの大きなものに対して行います。同じ画像を複数回メモリに保持する必要はありません。

最初に回答を書いたとき、静的変数が実際にどのように機能するかわかりませんでした。私は得static finalstatic混同しました。静的変数では、新しい値を割り当てることができます。static final は不変です。それらは変更できません。

于 2012-09-19T10:37:19.903 に答える
7

このプログラミング手法は、オブジェクト指向プログラミング パラダイムを弱体化させるため、純粋なオブジェクト指向言語 (Java など) では不適切です。それらは機能しますが、複数のバージョンが必要であることに気付いたら、それを実現するために多くのリファクタリングが必要になります。

メソッド呼び出しを介してあまりにも多くのパラメーターを処理するのは面倒だと思われる場合。それらすべてを保持するオブジェクトを作成し(Peter Lawreyの回答、「コンテキスト」オブジェクトを参照)、このオブジェクトのみを渡します。次に、そのオブジェクトで「単純なドット表記」を再び使用できます。

次のポイント: テスト。単体テストのためにいくつかの静的フィールドをプロキシまたはその他のテスト用のものに置き換える必要がある場合、基本的には失敗します。コンテキスト オブジェクトを使用すると、別のコンテキスト オブジェクトを単体テストに簡単に渡すことができます。

あなたが言及したUtilityクラスは、基本的にそのようなコンテキストオブジェクトの良い候補です。すべてのフィールドを非静的にし、そのクラスのオブジェクトを必要なコードに渡すだけです。

私が statics を使用して失敗した例を 1 つ挙げることができます。私はかつてコンパイラーを書きました。そして、コンパイルの実行中に、一度だけ必要なコンテキストのもの (シンボル テーブルなど) がたくさんあると思ったので、それらをすべて静的変数として追加しました。その後、マルチスレッド コンパイルと、クライアントがコンパイル要求を送信するまでコンパイラが常にアイドル モードで実行される「サーバー」モードを許可することにしました (これにより、Java の長い起動時間が節約されます)。今、私はめちゃくちゃになりました。現在、複数の並行コンテキスト (並行コンパイラ スレッド) がありましたが、すべてのコンテキストは静的変数を介して共有されていました。すべてのスタティックをコンテキスト オブジェクトに置き換えるのに約 1 週間かかり、多数のバグが発生しました。

于 2012-09-19T10:41:46.910 に答える
3

悪い。スタティックを切り取るを参照してください。

私の意見では、静的変数は 1 つまたは複数のオブジェクトで構成されますが、そのオブジェクトは形式が正しくありません: クラスで編成されていない (型階層がない)、カプセル化が不適切で、単一のインスタンスに制限されている (これは、将来、複数のインスタンスが必要になったときに問題を引き起こす可能性があります)。 .

于 2012-09-19T10:42:16.310 に答える
3

静的に宣言された変数は、プログラムが実行されるまでメモリ内にとどまるため、余分なスペースが必要になります。

値を長期間使用/保持する場合は、static の使用が有益な場合がありますが、すべての変数を static として宣言することは推奨されておらず、良い方法でもありません。すべての値を static として宣言する習慣を付けると、プログラムは不要なメモリを消費します。

その静的変数以外は、スコープ、抽象化、およびカプセル化が発泡オブジェクトとともに定義されるOOPSの概念に準拠していません。これにより、自由に変数を呼び出して削除できます。

静的変数を使用することの最大の欠点は、限られたメモリ空間 (モバイル アプリケーションなど) で作業している場合に現れます。この場合、アプリケーションが変数によって占有されすぎてメモリ空間が少なくなると、アプリケーションがクラッシュします。

値を永続的に保存したい場合は、データベースやファイルなど、他の方法で作業を簡単かつクリーンにすることができます。ちょうど私の2セント。

于 2012-09-19T10:44:12.803 に答える